1 /* 2 * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.openjdk.bench.java.lang.reflect.proxy; 24 25 import java.util.List; 26 27 import org.openjdk.jmh.annotations.Benchmark; 28 import org.openjdk.jmh.annotations.BenchmarkMode; 29 import org.openjdk.jmh.annotations.CompilerControl; 30 import org.openjdk.jmh.annotations.Fork; 31 import org.openjdk.jmh.annotations.Measurement; 32 import org.openjdk.jmh.annotations.Mode; 33 import org.openjdk.jmh.annotations.OutputTimeUnit; 34 import org.openjdk.jmh.annotations.Scope; 35 import org.openjdk.jmh.annotations.Setup; 36 import org.openjdk.jmh.annotations.State; 37 import org.openjdk.jmh.annotations.Warmup; 38 39 import org.openjdk.jmh.infra.Blackhole; 40 41 import java.lang.reflect.InvocationHandler; 42 import java.lang.reflect.InvocationTargetException; 43 import java.lang.reflect.Method; 44 import java.lang.reflect.Modifier; 45 import java.util.concurrent.TimeUnit; 46 47 /** 48 * Benchmark measuring java.lang.reflect.ProxyGenerator.generateProxyClass. 49 * It bypasses the cache of proxies to measure the time to construct a proxy. 50 */ 51 @Warmup(iterations = 5) 52 @Measurement(iterations = 10) 53 @Fork(value = 1) 54 @BenchmarkMode(Mode.AverageTime) 55 @OutputTimeUnit(TimeUnit.NANOSECONDS) 56 @State(Scope.Thread) 57 public class ProxyPerf { 58 59 /** 60 * Sample results from a Dell T7610. 61 * Benchmark Mode Cnt Score Error Units 62 * ProxyPerf.genIntf_1 avgt 10 35325.428 +/- 780.459 ns/op 63 * ProxyPerf.genIntf_1_V49 avgt 10 34309.423 +/- 727.188 ns/op 64 * ProxyPerf.genStringsIntf_3 avgt 10 46600.366 +/- 663.812 ns/op 65 * ProxyPerf.genStringsIntf_3_V49 avgt 10 45911.817 +/- 1598.536 ns/op 66 * ProxyPerf.genZeroParams avgt 10 33245.048 +/- 437.988 ns/op 67 * ProxyPerf.genZeroParams_V49 avgt 10 32954.254 +/- 1041.932 ns/op 68 * ProxyPerf.getPrimsIntf_2 avgt 10 43987.819 +/- 837.443 ns/op 69 * ProxyPerf.getPrimsIntf_2_V49 avgt 10 42863.462 +/- 1193.480 ns/op 70 */ 71 72 public interface Intf_1 { 73 public Object mL(Object o); 74 } 75 76 public interface Intf_2 { 77 public int m1I(int i); 78 public long m2IJ(int i, long l); 79 } 80 81 public interface Intf_3 { 82 public void mString(String s1); 83 public String m2String(String s1); 84 public String m2String(String s1, String s2); 85 } 86 87 private InvocationHandler handler; 88 private ClassLoader classloader; 89 private Method proxyGen; 90 private Method proxyGenV49; 91 92 @Setup 93 public void setup() { 94 try { 95 handler = (Object proxy, Method method, Object[] args) -> null; 96 classloader = ClassLoader.getSystemClassLoader(); 97 Class<?> proxyGenClass = Class.forName("java.lang.reflect.ProxyGenerator"); 98 proxyGen = proxyGenClass.getDeclaredMethod("generateProxyClass", 99 ClassLoader.class, String.class, java.util.List.class, int.class); 100 proxyGen.setAccessible(true); 101 102 // Init access to the old Proxy generator 103 Class<?> proxyGenClassV49 = Class.forName("java.lang.reflect.ProxyGenerator_v49"); 104 proxyGenV49 = proxyGenClassV49.getDeclaredMethod("generateProxyClass", 105 String.class, java.util.List.class, int.class); 106 proxyGenV49.setAccessible(true); 107 108 } catch (Exception ex) { 109 ex.printStackTrace(); 110 throw new RuntimeException("ProxyClass setup fails", ex); 111 } 112 } 113 114 @Benchmark 115 public void genZeroParams(Blackhole bh) throws Exception { 116 List<Class<?>> interfaces = List.of(Runnable.class); 117 bh.consume(proxyGen.invoke(null, classloader, "ProxyImpl", interfaces, 1)); 118 } 119 120 @Benchmark 121 public void genIntf_1(Blackhole bh) throws Exception { 122 List<Class<?>> interfaces = List.of(Intf_1.class); 123 bh.consume(proxyGen.invoke(null, classloader, "ProxyImpl", interfaces, 1)); 124 } 125 126 @Benchmark 127 public void getPrimsIntf_2(Blackhole bh) throws Exception { 128 List<Class<?>> interfaces = List.of(Intf_2.class); 129 bh.consume(proxyGen.invoke(null, classloader, "ProxyImpl", interfaces, 1)); 130 } 131 @Benchmark 132 public void genStringsIntf_3(Blackhole bh) throws Exception { 133 List<Class<?>> interfaces = List.of(Intf_3.class); 134 bh.consume(proxyGen.invoke(null, classloader, "ProxyImpl", interfaces, 1)); 135 } 136 137 // Generate using the V49inal generator for comparison 138 139 @Benchmark 140 public void genZeroParams_V49(Blackhole bh) throws Exception { 141 List<Class<?>> interfaces = List.of(Runnable.class); 142 bh.consume(proxyGenV49.invoke(null, "ProxyImpl", interfaces, 1)); 143 } 144 145 @Benchmark 146 public void genIntf_1_V49(Blackhole bh) throws Exception { 147 List<Class<?>> interfaces = List.of(Intf_1.class); 148 bh.consume(proxyGenV49.invoke(null, "ProxyImpl", interfaces, 1)); 149 } 150 151 @Benchmark 152 public void getPrimsIntf_2_V49(Blackhole bh) throws Exception { 153 List<Class<?>> interfaces = List.of(Intf_2.class); 154 bh.consume(proxyGenV49.invoke(null, "ProxyImpl", interfaces, 1)); 155 } 156 @Benchmark 157 public void genStringsIntf_3_V49(Blackhole bh) throws Exception { 158 List<Class<?>> interfaces = List.of(Intf_3.class); 159 bh.consume(proxyGenV49.invoke(null, "ProxyImpl", interfaces, 1)); 160 } 161 162 }