VarHandle instance methods performance

Roger Riggs Roger.Riggs at oracle.com
Thu Apr 25 13:07:04 UTC 2019


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();
>             
>          }
>
>      }
>
> }
>
>



More information about the core-libs-dev mailing list