Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/util/ArrayList/RangeCheckMicroBenchmark.java
38811 views
/*1* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* This is not a regression test, but a micro-benchmark.25*26* I have run this as follows:27*28* repeat 5 for f in -client -server; do mergeBench dolphin . jr -dsa -da $f RangeCheckMicroBenchmark.java; done29*30*31* @author Martin Buchholz32*/3334import java.util.*;35import java.util.regex.Pattern;36import java.util.concurrent.CountDownLatch;3738public class RangeCheckMicroBenchmark {39abstract static class Job {40private final String name;41Job(String name) { this.name = name; }42String name() { return name; }43abstract void work() throws Throwable;44}4546private static void collectAllGarbage() {47final CountDownLatch drained = new CountDownLatch(1);48try {49System.gc(); // enqueue finalizable objects50new Object() { protected void finalize() {51drained.countDown(); }};52System.gc(); // enqueue detector53drained.await(); // wait for finalizer queue to drain54System.gc(); // cleanup finalized objects55} catch (InterruptedException e) { throw new Error(e); }56}5758/**59* Runs each job for long enough that all the runtime compilers60* have had plenty of time to warm up, i.e. get around to61* compiling everything worth compiling.62* Returns array of average times per job per run.63*/64private static long[] time0(Job ... jobs) throws Throwable {65final long warmupNanos = 10L * 1000L * 1000L * 1000L;66long[] nanoss = new long[jobs.length];67for (int i = 0; i < jobs.length; i++) {68collectAllGarbage();69long t0 = System.nanoTime();70long t;71int j = 0;72do { jobs[i].work(); j++; }73while ((t = System.nanoTime() - t0) < warmupNanos);74nanoss[i] = t/j;75}76return nanoss;77}7879private static void time(Job ... jobs) throws Throwable {8081long[] warmup = time0(jobs); // Warm up run82long[] nanoss = time0(jobs); // Real timing run83long[] milliss = new long[jobs.length];84double[] ratios = new double[jobs.length];8586final String nameHeader = "Method";87final String millisHeader = "Millis";88final String ratioHeader = "Ratio";8990int nameWidth = nameHeader.length();91int millisWidth = millisHeader.length();92int ratioWidth = ratioHeader.length();9394for (int i = 0; i < jobs.length; i++) {95nameWidth = Math.max(nameWidth, jobs[i].name().length());9697milliss[i] = nanoss[i]/(1000L * 1000L);98millisWidth = Math.max(millisWidth,99String.format("%d", milliss[i]).length());100101ratios[i] = (double) nanoss[i] / (double) nanoss[0];102ratioWidth = Math.max(ratioWidth,103String.format("%.3f", ratios[i]).length());104}105106String format = String.format("%%-%ds %%%dd %%%d.3f%%n",107nameWidth, millisWidth, ratioWidth);108String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",109nameWidth, millisWidth, ratioWidth);110System.out.printf(headerFormat, "Method", "Millis", "Ratio");111112// Print out absolute and relative times, calibrated against first job113for (int i = 0; i < jobs.length; i++)114System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]);115}116117private static String keywordValue(String[] args, String keyword) {118for (String arg : args)119if (arg.startsWith(keyword))120return arg.substring(keyword.length() + 1);121return null;122}123124private static int intArg(String[] args, String keyword, int defaultValue) {125String val = keywordValue(args, keyword);126return val == null ? defaultValue : Integer.parseInt(val);127}128129private static Pattern patternArg(String[] args, String keyword) {130String val = keywordValue(args, keyword);131return val == null ? null : Pattern.compile(val);132}133134private static Job[] filter(Pattern filter, Job[] jobs) {135if (filter == null) return jobs;136Job[] newJobs = new Job[jobs.length];137int n = 0;138for (Job job : jobs)139if (filter.matcher(job.name()).find())140newJobs[n++] = job;141// Arrays.copyOf not available in JDK 5142Job[] ret = new Job[n];143System.arraycopy(newJobs, 0, ret, 0, n);144return ret;145}146147private static void deoptimize(ArrayList<Integer> list) {148for (Integer x : list)149if (x == null)150throw new Error();151}152153/**154* Usage: [iterations=N] [size=N] [filter=REGEXP]155*/156public static void main(String[] args) throws Throwable {157final int iterations = intArg(args, "iterations", 30000);158final int size = intArg(args, "size", 1000);159final Pattern filter = patternArg(args, "filter");160161final ArrayList<Integer> list = new ArrayList<Integer>();162final Random rnd = new Random();163for (int i = 0; i < size; i++)164list.add(rnd.nextInt());165166final Job[] jobs = {167new Job("get") { void work() {168for (int i = 0; i < iterations; i++) {169for (int k = 0; k < size; k++)170if (list.get(k) == 42)171throw new Error();172}173deoptimize(list);}},174new Job("set") { void work() {175Integer[] xs = list.toArray(new Integer[size]);176for (int i = 0; i < iterations; i++) {177for (int k = 0; k < size; k++)178list.set(k, xs[k]);179}180deoptimize(list);}},181new Job("get/set") { void work() {182for (int i = 0; i < iterations; i++) {183for (int k = 0; k < size; k++)184list.set(k, list.get(size - k - 1));185}186deoptimize(list);}},187new Job("add/remove at end") { void work() {188Integer x = rnd.nextInt();189for (int i = 0; i < iterations; i++) {190for (int k = 0; k < size - 1; k++) {191list.add(size, x);192list.remove(size);193}194}195deoptimize(list);}},196new Job("subList get") { void work() {197List<Integer> sublist = list.subList(0, list.size());198for (int i = 0; i < iterations; i++) {199for (int k = 0; k < size; k++)200if (sublist.get(k) == 42)201throw new Error();202}203deoptimize(list);}},204new Job("subList set") { void work() {205List<Integer> sublist = list.subList(0, list.size());206Integer[] xs = sublist.toArray(new Integer[size]);207for (int i = 0; i < iterations; i++) {208for (int k = 0; k < size; k++)209sublist.set(k, xs[k]);210}211deoptimize(list);}},212new Job("subList get/set") { void work() {213List<Integer> sublist = list.subList(0, list.size());214for (int i = 0; i < iterations; i++) {215for (int k = 0; k < size; k++)216sublist.set(k, sublist.get(size - k - 1));217}218deoptimize(list);}},219new Job("subList add/remove at end") { void work() {220List<Integer> sublist = list.subList(0, list.size());221Integer x = rnd.nextInt();222for (int i = 0; i < iterations; i++) {223for (int k = 0; k < size - 1; k++) {224sublist.add(size, x);225sublist.remove(size);226}227}228deoptimize(list);}}229};230231time(filter(filter, jobs));232}233}234235236