1 /* 2 * Copyright (c) 2007, 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 24 /* 25 * This is not a regression test, but a micro-benchmark. 26 * 27 * I have run this as follows: 28 * 29 * repeat 5 for f in -client -server; do mergeBench dolphin . jr -dsa -da $f TypeCheckMicroBenchmark.java; done 30 * 31 * 32 * @author Martin Buchholz 33 */ 34 35 import java.util.*; 36 37 public class TypeCheckMicroBenchmark { 38 abstract static class Job { 39 private final String name; 40 Job(String name) { this.name = name; } 41 String name() { return name; } 42 abstract void work() throws Throwable; 43 } 44 45 private static void collectAllGarbage() { 46 final java.util.concurrent.CountDownLatch drained 47 = new java.util.concurrent.CountDownLatch(1); 48 try { 49 System.gc(); // enqueue finalizable objects 50 new Object() { protected void finalize() { 51 drained.countDown(); }}; 52 System.gc(); // enqueue detector 53 drained.await(); // wait for finalizer queue to drain 54 System.gc(); // cleanup finalized objects 55 } catch (InterruptedException e) { throw new Error(e); } 56 } 57 58 /** 59 * Runs each job for long enough that all the runtime compilers 60 * have had plenty of time to warm up, i.e. get around to 61 * compiling everything worth compiling. 62 * Returns array of average times per job per run. 63 */ 64 private static long[] time0(Job ... jobs) throws Throwable { 65 final long warmupNanos = 10L * 1000L * 1000L * 1000L; 66 long[] nanoss = new long[jobs.length]; 67 for (int i = 0; i < jobs.length; i++) { 68 collectAllGarbage(); 69 long t0 = System.nanoTime(); 70 long t; 71 int j = 0; 72 do { jobs[i].work(); j++; } 73 while ((t = System.nanoTime() - t0) < warmupNanos); 74 nanoss[i] = t/j; 75 } 76 return nanoss; 77 } 78 79 private static void time(Job ... jobs) throws Throwable { 80 81 long[] warmup = time0(jobs); // Warm up run 82 long[] nanoss = time0(jobs); // Real timing run 83 long[] milliss = new long[jobs.length]; 84 double[] ratios = new double[jobs.length]; 85 86 final String nameHeader = "Method"; 87 final String millisHeader = "Millis"; 88 final String ratioHeader = "Ratio"; 89 90 int nameWidth = nameHeader.length(); 91 int millisWidth = millisHeader.length(); 92 int ratioWidth = ratioHeader.length(); 93 94 for (int i = 0; i < jobs.length; i++) { 95 nameWidth = Math.max(nameWidth, jobs[i].name().length()); 96 97 milliss[i] = nanoss[i]/(1000L * 1000L); 98 millisWidth = Math.max(millisWidth, 99 String.format("%d", milliss[i]).length()); 100 101 ratios[i] = (double) nanoss[i] / (double) nanoss[0]; 102 ratioWidth = Math.max(ratioWidth, 103 String.format("%.3f", ratios[i]).length()); 104 } 105 106 String format = String.format("%%-%ds %%%dd %%%d.3f%%n", 107 nameWidth, millisWidth, ratioWidth); 108 String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n", 109 nameWidth, millisWidth, ratioWidth); 110 System.out.printf(headerFormat, "Method", "Millis", "Ratio"); 111 112 // Print out absolute and relative times, calibrated against first job 113 for (int i = 0; i < jobs.length; i++) 114 System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]); 115 } 116 117 private static String keywordValue(String[] args, String keyword) { 118 for (String arg : args) 119 if (arg.startsWith(keyword)) 120 return arg.substring(keyword.length() + 1); 121 return null; 122 } 123 124 private static int intArg(String[] args, String keyword, int defaultValue) { 125 String val = keywordValue(args, keyword); 126 return val == null ? defaultValue : Integer.parseInt(val); 127 } 128 129 private static java.util.regex.Pattern patternArg(String[] args, 130 String keyword) { 131 String val = keywordValue(args, keyword); 132 return val == null ? null : java.util.regex.Pattern.compile(val); 133 } 134 135 private static Job[] filter(java.util.regex.Pattern filter, 136 Job[] jobs) { 137 if (filter == null) return jobs; 138 Job[] newJobs = new Job[jobs.length]; 139 int n = 0; 140 for (Job job : jobs) 141 if (filter.matcher(job.name()).find()) 142 newJobs[n++] = job; 143 // Arrays.copyOf not available in JDK 5 144 Job[] ret = new Job[n]; 145 System.arraycopy(newJobs, 0, ret, 0, n); 146 return ret; 147 } 148 149 /** 150 * Usage: [iterations=N] [size=N] [filter=REGEXP] 151 */ 152 public static void main(String[] args) throws Throwable { 153 final int iterations = intArg(args, "iterations", 30000); 154 final int size = intArg(args, "size", 1000); 155 final java.util.regex.Pattern filter 156 = patternArg(args, "filter"); 157 158 final List<Integer> list = new ArrayList<Integer>(); 159 final Random rnd = new Random(); 160 for (int i = 0; i < size; i++) 161 list.add(rnd.nextInt()); 162 final Class klazz = Integer.class; 163 164 final Job[] jobs = { 165 new Job("toArray(T[])") { void work() { 166 Object[] a = new Integer[0]; 167 for (int i = 0; i < iterations; i++) { 168 try { list.toArray(a); } 169 catch (ArrayStoreException ase) { 170 throw new ClassCastException(); }}}}, 171 new Job("isInstance") { void work() { 172 for (int i = 0; i < iterations; i++) { 173 for (Object x : list.toArray()) 174 if (! (x != null && klazz.isInstance(x))) 175 throw new ClassCastException(); }}}, 176 new Job("Class.cast") { void work() { 177 for (int i = 0; i < iterations; i++) { 178 for (Object x : list.toArray()) 179 klazz.cast(x); }}}, 180 new Job("write into array") { void work() { 181 Object[] a = new Integer[1]; 182 for (int i = 0; i < iterations; i++) { 183 for (Object x : list.toArray()) { 184 try { a[0] = x; } 185 catch (ArrayStoreException ignore) { 186 throw new ClassCastException(); }}}}}, 187 new Job("write into dynamic array") { void work() { 188 for (int i = 0; i < iterations; i++) { 189 for (Object x : list.toArray()) { 190 Object[] a = (Object[]) 191 java.lang.reflect.Array.newInstance(klazz, 1); 192 try { a[0] = x; } 193 catch (ArrayStoreException ignore) { 194 throw new ClassCastException(); }}}}} 195 }; 196 197 time(filter(filter, jobs)); 198 } 199 }