Path: blob/master/test/jdk/java/util/ArrayList/RangeCheckMicroBenchmark.java
41149 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.ArrayList;35import java.util.Arrays;36import java.util.List;37import java.util.Random;38import java.util.concurrent.CountDownLatch;39import java.util.regex.Pattern;4041import static java.util.stream.Collectors.toList;4243public class RangeCheckMicroBenchmark {44abstract static class Job {45private final String name;46Job(String name) { this.name = name; }47String name() { return name; }48abstract void work() throws Throwable;49}5051private static void collectAllGarbage() {52final CountDownLatch drained = new CountDownLatch(1);53try {54System.gc(); // enqueue finalizable objects55new Object() { protected void finalize() {56drained.countDown(); }};57System.gc(); // enqueue detector58drained.await(); // wait for finalizer queue to drain59System.gc(); // cleanup finalized objects60} catch (InterruptedException e) { throw new Error(e); }61}6263/**64* Runs each job for long enough that all the runtime compilers65* have had plenty of time to warm up, i.e. get around to66* compiling everything worth compiling.67* Returns array of average times per job per run.68*/69private static long[] time0(Job ... jobs) throws Throwable {70final long warmupNanos = 10L * 1000L * 1000L * 1000L;71long[] nanoss = new long[jobs.length];72for (int i = 0; i < jobs.length; i++) {73collectAllGarbage();74long t0 = System.nanoTime();75long t;76int j = 0;77do { jobs[i].work(); j++; }78while ((t = System.nanoTime() - t0) < warmupNanos);79nanoss[i] = t/j;80}81return nanoss;82}8384private static void time(Job ... jobs) throws Throwable {8586long[] warmup = time0(jobs); // Warm up run87long[] nanoss = time0(jobs); // Real timing run88long[] milliss = new long[jobs.length];89double[] ratios = new double[jobs.length];9091final String nameHeader = "Method";92final String millisHeader = "Millis";93final String ratioHeader = "Ratio";9495int nameWidth = nameHeader.length();96int millisWidth = millisHeader.length();97int ratioWidth = ratioHeader.length();9899for (int i = 0; i < jobs.length; i++) {100nameWidth = Math.max(nameWidth, jobs[i].name().length());101102milliss[i] = nanoss[i]/(1000L * 1000L);103millisWidth = Math.max(millisWidth,104String.format("%d", milliss[i]).length());105106ratios[i] = (double) nanoss[i] / (double) nanoss[0];107ratioWidth = Math.max(ratioWidth,108String.format("%.3f", ratios[i]).length());109}110111String format = String.format("%%-%ds %%%dd %%%d.3f%%n",112nameWidth, millisWidth, ratioWidth);113String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",114nameWidth, millisWidth, ratioWidth);115System.out.printf(headerFormat, "Method", "Millis", "Ratio");116117// Print out absolute and relative times, calibrated against first job118for (int i = 0; i < jobs.length; i++)119System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]);120}121122private static String keywordValue(String[] args, String keyword) {123for (String arg : args)124if (arg.startsWith(keyword))125return arg.substring(keyword.length() + 1);126return null;127}128129private static int intArg(String[] args, String keyword, int defaultValue) {130String val = keywordValue(args, keyword);131return val == null ? defaultValue : Integer.parseInt(val);132}133134private static Pattern patternArg(String[] args, String keyword) {135String val = keywordValue(args, keyword);136return val == null ? null : Pattern.compile(val);137}138139private static Job[] filter(Pattern filter, Job[] jobs) {140return (filter == null) ? jobs141: Arrays.stream(jobs)142.filter(job -> filter.matcher(job.name()).find())143.collect(toList())144.toArray(new Job[0]);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<>();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