You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@jmeter.apache.org by bu...@apache.org on 2014/11/10 11:45:36 UTC

[Bug 54453] Performance enhancements : Replace Random by ThreadLocalRandom

https://issues.apache.org/bugzilla/show_bug.cgi?id=54453

--- Comment #6 from Mikhail Epikhin <ep...@gmail.com> ---
Hello, Philippe!

Your patch is good, but why not use "rand =
ThreadLocalRandom.current().nextLong(min, max);" instead of "rand = min +
(ThreadLocalRandom.current().nextLong(max - min + 1));" ?
 It's more clearly and readability.

I tested this patch on GNU/Linux with 4 JDK (hs_jdk1.7.0_71, hs_jdk1.8.0_25,
hs_jdk1.9.0_ea_b37, zulu_1.8.0_25-8.4.0.1-x86lx64). All works fine.
I created some benchmarks with 1 dummy sampler (from jmeter-plugins) and 100
${__Random} functions in him (for more powerful amplification), and tested
scalability on machine with large number of cores.

Some time before you removed synchronized block from ${__Random} function
https://github.com/apache/jmeter/commit/f03a8bdbe5ba31d9f42adf816887c714cd8c7dce#diff-d388a962eb391a4d5b119abef27b819dL72
 And this commit improves a little bit performance. But scalability is not so
good. With large number of threads we have new contention. Previous contention
on synchronized block, and new on Math.random block.

At all tests with large number of threads i have many threads spending on this
stacks:

"Thread Group 1-12" #33 prio=5 os_prio=0 tid=0x00007fc2cc039800 nid=0x1677
runnable [0x00007fc3290a8000]
   java.lang.Thread.State: RUNNABLE
--->    at java.util.Random.next(Random.java:204)
--->    at java.util.Random.nextDouble(Random.java:532)
--->    at java.lang.Math.random(Math.java:773)
        at org.apache.jmeter.functions.Random.execute(Random.java:65)
        at
org.apache.jmeter.engine.util.CompoundVariable.execute(CompoundVariable.java:142)
        at
org.apache.jmeter.engine.util.CompoundVariable.execute(CompoundVariable.java:118)
        at
org.apache.jmeter.testelement.property.FunctionProperty.getStringValue(FunctionProperty.java:101)
        at
org.apache.jmeter.testelement.AbstractTestElement.getPropertyAsString(AbstractTestElement.java:274)
        at
kg.apc.jmeter.samplers.DummySampler.getRequestData(DummySampler.java:111)
        at kg.apc.jmeter.samplers.DummySampler.sample(DummySampler.java:38)
        at
org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:431)
        at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:258)
        at java.lang.Thread.run(Thread.java:745)

I looked at HotSpot JDK1.8 sources, and found that we have contention on
Compare-and-Swap at "seed" atomic value.

     198     protected int next(int bits) {
     199         long oldseed, nextseed;
     200         AtomicLong seed = this.seed;
     201         do {
     202             oldseed = seed.get();
     203             nextseed = (oldseed * multiplier + addend) & mask;
---> 204         } while (!seed.compareAndSet(oldseed, nextseed));
     205         return (int)(nextseed >>> (48 - bits));

With your ThreadLocal patch we just sharded this atomic seed values. So,
throughput scales good:) It's linearly scales with number of threads!

What do your think about include this patch into Apache JMeter 2.12?

-- 
You are receiving this mail because:
You are the assignee for the bug.