Huh, interesting.

I have:

(defn foo' [x]
  (if (> x 0)
    (inc x)
    (let [res (locking o (dec x))] res)))

(defn foo'' [x]
  (if (> x 0)
    (inc x)
    (locking o
      (dec x))))

foo' is fast, but foo'' is slow. So something about wrapping the locking 
clause in a let makes it fast. Still no idea why.

On Sunday, November 3, 2013 9:30:45 AM UTC-8, Michał Marczyk wrote:
>
> You have a typo in foo -- monitor-exit's argument is 0 (zero) rather 
> than o (the sentinel object). 
>
> Besides that, in foo both monitor-enter and monitor-exit get their 
> arguments from a Var. Rewriting to use locking, which first puts the 
> object whose monitor will be used in a local (that is, (let [lockee o] 
> ...), where ... performs the locking using the newly introduced 
> local), gives timings identical to those of bar and baz: 
>
> (defn foo' [x] 
>   (if (> x 0) 
>     (inc x) 
>     (let [res (locking o (dec x))] res))) 
>
> So this is one reason not to use monitor-enter and monitor-exit 
> directly. Another reason is that locking guarantees that the monitor 
> will be released (by using try / finally, and of course by preventing 
> situations where the matching monitor-enter & monitor-exit operate on 
> different objects). 
>
> In fact, both monitor-enter and monitor-exit carry docstrings which 
> explicitly say that they should not be used in user code and point to 
> locking as the user-facing equivalent to Java's synchronized. 
>
> Cheers, 
> Michał 
>
>
> On 1 November 2013 19:34, Michael Blume <blume...@gmail.com <javascript:>> 
> wrote: 
> > https://github.com/MichaelBlume/perf-test 
> > 
> > (ns perf-test 
> >   (:use (criterium core)) 
> >   (:gen-class)) 
> > 
> > (def o (Object.)) 
> > 
> > (defn foo [x] 
> >   (if (> x 0) 
> >     (inc x) 
> >     (do 
> >       (monitor-enter o) 
> >       (let [res (dec x)] 
> >         (monitor-exit 0) 
> >         res)))) 
> > 
> > (defn bar [x] 
> >   (if (> x 0) 
> >     (inc x) 
> >     (dec x))) 
> > 
> > (defn locking-part [x l] 
> >   (monitor-enter l) 
> >   (let [res (dec x)] 
> >     (monitor-exit l) 
> >     res)) 
> > 
> > (defn baz [x] 
> >   (if (> x 0) 
> >     (inc x) 
> >     (locking-part x o))) 
> > 
> > (defn -main [] 
> >   (println "benching foo") 
> >   (bench (foo 5) :verbose) 
> >   (println "benching bar") 
> >   (bench (bar 5) :verbose) 
> >   (println "benching baz") 
> >   (bench (baz 5) :verbose) 
> >   (println "done benching")) 
> > 
> > 
> > 
> > I'm only ever calling these functions with positive values, so the 
> > monitor-enter branch should never be entered. Nevertheless, the 
> performance 
> > of foo is much worse than bar or baz. 
> > 
> > The best guess I've got is that the fact that lock-taking is involved 
> > somehow changes how the function is compiled, somehow making the 
> function 
> > slower. If the practical upshot is that I shouldn't write functions that 
> > only sometimes lock -- that the locking part of a function should always 
> be 
> > its own function -- then I can do that, but I'm curious why. 
> > 
> > $ lein uberjar 
> > Compiling perf-test 
> > Created /Users/mike/perf-test/target/perf-test-0.1.0-SNAPSHOT.jar 
> > Created 
> /Users/mike/perf-test/target/perf-test-0.1.0-SNAPSHOT-standalone.jar 
> > $ java -jar -server target/perf-test-0.1.0-SNAPSHOT-standalone.jar 
> > benching foo 
> > WARNING: Final GC required 1.5974571326266802 % of runtime 
> > x86_64 Mac OS X 10.8.3 4 cpu(s) 
> > Java HotSpot(TM) 64-Bit Server VM 24.0-b28 
> > Runtime arguments: 
> > Evaluation count : 391582560 in 60 samples of 6526376 calls. 
> >       Execution time sample mean : 167.426696 ns 
> >              Execution time mean : 167.459429 ns 
> > Execution time sample std-deviation : 4.079466 ns 
> >     Execution time std-deviation : 4.097819 ns 
> >    Execution time lower quantile : 160.742869 ns ( 2.5%) 
> >    Execution time upper quantile : 175.453376 ns (97.5%) 
> >                    Overhead used : 1.634996 ns 
> > 
> > Found 2 outliers in 60 samples (3.3333 %) 
> > low-severe 2 (3.3333 %) 
> >  Variance from outliers : 12.5602 % Variance is moderately inflated by 
> > outliers 
> > benching bar 
> > x86_64 Mac OS X 10.8.3 4 cpu(s) 
> > Java HotSpot(TM) 64-Bit Server VM 24.0-b28 
> > Runtime arguments: 
> > Evaluation count : 2174037300 in 60 samples of 36233955 calls. 
> >       Execution time sample mean : 26.068923 ns 
> >              Execution time mean : 26.066422 ns 
> > Execution time sample std-deviation : 0.887937 ns 
> >     Execution time std-deviation : 0.916861 ns 
> >    Execution time lower quantile : 23.996763 ns ( 2.5%) 
> >    Execution time upper quantile : 27.911936 ns (97.5%) 
> >                    Overhead used : 1.634996 ns 
> > 
> > Found 3 outliers in 60 samples (5.0000 %) 
> > low-severe 1 (1.6667 %) 
> > low-mild 1 (1.6667 %) 
> > high-mild 1 (1.6667 %) 
> >  Variance from outliers : 22.1874 % Variance is moderately inflated by 
> > outliers 
> > benching baz 
> > x86_64 Mac OS X 10.8.3 4 cpu(s) 
> > Java HotSpot(TM) 64-Bit Server VM 24.0-b28 
> > Runtime arguments: 
> > Evaluation count : 2270676660 in 60 samples of 37844611 calls. 
> >       Execution time sample mean : 25.834142 ns 
> >              Execution time mean : 25.837429 ns 
> > Execution time sample std-deviation : 0.718382 ns 
> >     Execution time std-deviation : 0.729431 ns 
> >    Execution time lower quantile : 24.837925 ns ( 2.5%) 
> >    Execution time upper quantile : 27.595781 ns (97.5%) 
> >                    Overhead used : 1.634996 ns 
> > 
> > Found 4 outliers in 60 samples (6.6667 %) 
> > low-severe 2 (3.3333 %) 
> > low-mild 2 (3.3333 %) 
> >  Variance from outliers : 15.7591 % Variance is moderately inflated by 
> > outliers 
> > done benching 
> > 
> > -- 
> > -- 
> > You received this message because you are subscribed to the Google 
> > Groups "Clojure" group. 
> > To post to this group, send email to clo...@googlegroups.com<javascript:> 
> > Note that posts from new members are moderated - please be patient with 
> your 
> > first post. 
> > To unsubscribe from this group, send email to 
> > clojure+u...@googlegroups.com <javascript:> 
> > For more options, visit this group at 
> > http://groups.google.com/group/clojure?hl=en 
> > --- 
> > You received this message because you are subscribed to the Google 
> Groups 
> > "Clojure" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> an 
> > email to clojure+u...@googlegroups.com <javascript:>. 
> > For more options, visit https://groups.google.com/groups/opt_out. 
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to