Hi Frank,

These performance measurements would be good to add as JMH tests in open/test/micro...

Thanks, Roger


On 04/24/2019 05:51 AM, Frank Yuan wrote:
Hi Aleksey

I happened to see the performance to access a field by VarHandle API is much 
worse than the native access.

I tested the following situations:
1. reading a volatile field directly
2. calling getVolatile against this volatile field
3. calling getVolatile against another non-volatile field

As my expectation, Situation 2 has similar performance with situation 3, but 
both of them have 100 times of situation 1 execution time in my test.

I think it should be due to some overhead, and it doesn't violate the JEP 193 
performance requirement. But I still can't figure out why it's so slow after 
runtime compiling? Hope you can give me some point. Thanks!


My test code is as below:

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;

public class Test5 {

     static final int iter_num = 100000000;
     private volatile int vf = 1;
     private int f = 1;
     final VarHandle vhf;
     final VarHandle vhvf;
     final ThreadMXBean threadMXBean;
public Test5 () throws Exception {
         vhf = MethodHandles.lookup().findVarHandle(
                 Test5.class, "f", int.class);
         vhvf = MethodHandles.lookup().findVarHandle(
                 Test5.class, "vf", int.class);
threadMXBean = ManagementFactory.getThreadMXBean(); //System.out.println(threadMXBean.isCurrentThreadCpuTimeSupported());
         //System.out.println(threadMXBean.isThreadCpuTimeEnabled());
     }

public void measGetVolatileField() {
         int tmpProgress = 0;
         long startCpu = threadMXBean.getCurrentThreadCpuTime();
         long startUser = threadMXBean.getCurrentThreadUserTime();
         for (int i = 0; i < iter_num; ++i) {
             tmpProgress += vf;
         }
long endCpu = threadMXBean.getCurrentThreadCpuTime();
         long endUser = threadMXBean.getCurrentThreadUserTime();
long durCpu = endCpu -startCpu;
         long durUser = endUser - startUser;
         System.out.println("measGetVolatileField");
         System.out.println("cpu time: " + durCpu);
         System.out.println("user time: " + durUser);
         System.out.println(tmpProgress);
     }
public void measGetVolatileFieldByVHWithVolatile() {
         int tmpProgress = 0;
         long startCpu = threadMXBean.getCurrentThreadCpuTime();
         long startUser = threadMXBean.getCurrentThreadUserTime();
         for (int i = 0; i < iter_num; ++i) {
             tmpProgress += (int) vhvf.getVolatile(this);
         }
long endCpu = threadMXBean.getCurrentThreadCpuTime();
         long endUser = threadMXBean.getCurrentThreadUserTime();
long durCpu = endCpu -startCpu;
         long durUser = endUser - startUser;
         System.out.println("measGetVolatileFieldByVHWithVolatile");
         System.out.println("cpu time: " + durCpu);
         System.out.println("user time: " + durUser);
         System.out.println(tmpProgress);
     }
public void measGetFieldByVHWithVolatile() {
         int tmpProgress = 0;
         long startCpu = threadMXBean.getCurrentThreadCpuTime();
         long startUser = threadMXBean.getCurrentThreadUserTime();
         for (int i = 0; i < iter_num; ++i) {
             tmpProgress += (int) vhf.getVolatile(this);
         }
long endCpu = threadMXBean.getCurrentThreadCpuTime();
         long endUser = threadMXBean.getCurrentThreadUserTime();
long durCpu = endCpu -startCpu;
         long durUser = endUser - startUser;
         System.out.println("measGetFieldByVHWithVolatile");
         System.out.println("cpu time: " + durCpu);
         System.out.println("user time: " + durUser);
         System.out.println(tmpProgress);
     }
public static void main(String[] args) throws Exception { for (int i = 0; i < 5; i++) {
             Test5 test = new Test5 ();
Thread threadA = new Thread(() -> test.measGetVolatileField());
             Thread threadB = new Thread(() -> 
test.measGetVolatileFieldByVHWithVolatile());
             Thread threadC = new Thread(() -> 
test.measGetFieldByVHWithVolatile());
threadA.start();
             threadA.join();
threadB.start();
             threadB.join();
threadC.start();
             threadC.join();
}

     }

}



Reply via email to