-
-
Notifications
You must be signed in to change notification settings - Fork 2
Overhead
Justin Conklin edited this page Aug 24, 2021
·
7 revisions
Since jmh-clojure can also run externally defined (normally in Java) benchmarks, let's compare two simple benchmarks for our baseline to measure overhead.
package demo;
import java.util.concurrent.ThreadLocalRandom;
import org.openjdk.jmh.annotations.*;
public class Native {
@Benchmark
public Object addBoxed (LongState a, LongState b) {
return a.boxedValue + b.boxedValue;
}
@Benchmark
public long addPrim (LongState a, LongState b) {
return a.primValue + b.primValue;
}
@State(Scope.Thread)
public static class LongState {
public Long boxedValue; // non-final on purpose
public long primValue;
public LongState () {
boxedValue = primValue = ThreadLocalRandom.current().nextLong(Integer.MAX_VALUE);
}
}
}
(ns demo.core)
(defn add-boxed [a b]
(+ a b))
(defn add-prim ^long [^long a ^long b]
(unchecked-add a b))
(defn random-long []
(rand Integer/MAX_VALUE))
We'll use the lein-jmh plugin to run our benchmarks. Here is the jmh.edn
file:
{:benchmarks [{:fn demo.core/add-boxed, :args [:long, :long]}
{:fn demo.core/add-prim, :args [:long, :long]}]
:states {:long {:fn demo.core/random-long, :scope :thread}}}
Now execute the following command:
lein jmh '{:externs [demo.Native], :only [:fn :method :score], :type :quick}'
# => ({:fn demo.core/add-boxed, :score [1.76108890554332E8 "ops/s"]}
# {:fn demo.core/add-prim, :score [3.96770743953259E8 "ops/s"]}
# {:method demo.Native/addBoxed, :score [1.83169450586705E8 "ops/s"]}
# {:method demo.Native/addPrim, :score [3.97466361792193E8 "ops/s"]})
We can see that the overhead introduced by this library is virtually non-existant. The boxed versions are there just to prove that Hotspot is not doing some clever optimization tricks to our code that would influence results.
Note that the Java state fields are non-final. For more on why this is, see here.
For more, please see "How It Works".
The complete code for this example can be found here.