Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/util/ArrayList/IteratorMicroBenchmark.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* Be patient; this runs for half an hour!26*27* I have run this as follows:28*29* for f in -client -server; do mergeBench dolphin . jr -dsa -da $f IteratorMicroBenchmark.java; done30*31*32* @author Martin Buchholz33*/3435import java.util.*;36import java.util.concurrent.*;37import java.util.regex.Pattern;3839public class IteratorMicroBenchmark {40abstract static class Job {41private final String name;42public Job(String name) { this.name = name; }43public String name() { return name; }44public abstract void work() throws Throwable;45}4647private static void collectAllGarbage() {48final java.util.concurrent.CountDownLatch drained49= new java.util.concurrent.CountDownLatch(1);50try {51System.gc(); // enqueue finalizable objects52new Object() { protected void finalize() {53drained.countDown(); }};54System.gc(); // enqueue detector55drained.await(); // wait for finalizer queue to drain56System.gc(); // cleanup finalized objects57} catch (InterruptedException e) { throw new Error(e); }58}5960/**61* Runs each job for long enough that all the runtime compilers62* have had plenty of time to warm up, i.e. get around to63* compiling everything worth compiling.64* Returns array of average times per job per run.65*/66private static long[] time0(Job ... jobs) throws Throwable {67final long warmupNanos = 10L * 1000L * 1000L * 1000L;68long[] nanoss = new long[jobs.length];69for (int i = 0; i < jobs.length; i++) {70collectAllGarbage();71long t0 = System.nanoTime();72long t;73int j = 0;74do { jobs[i].work(); j++; }75while ((t = System.nanoTime() - t0) < warmupNanos);76nanoss[i] = t/j;77}78return nanoss;79}8081private static void time(Job ... jobs) throws Throwable {8283long[] warmup = time0(jobs); // Warm up run84long[] nanoss = time0(jobs); // Real timing run85long[] milliss = new long[jobs.length];86double[] ratios = new double[jobs.length];8788final String nameHeader = "Method";89final String millisHeader = "Millis";90final String ratioHeader = "Ratio";9192int nameWidth = nameHeader.length();93int millisWidth = millisHeader.length();94int ratioWidth = ratioHeader.length();9596for (int i = 0; i < jobs.length; i++) {97nameWidth = Math.max(nameWidth, jobs[i].name().length());9899milliss[i] = nanoss[i]/(1000L * 1000L);100millisWidth = Math.max(millisWidth,101String.format("%d", milliss[i]).length());102103ratios[i] = (double) nanoss[i] / (double) nanoss[0];104ratioWidth = Math.max(ratioWidth,105String.format("%.3f", ratios[i]).length());106}107108String format = String.format("%%-%ds %%%dd %%%d.3f%%n",109nameWidth, millisWidth, ratioWidth);110String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",111nameWidth, millisWidth, ratioWidth);112System.out.printf(headerFormat, "Method", "Millis", "Ratio");113114// Print out absolute and relative times, calibrated against first job115for (int i = 0; i < jobs.length; i++)116System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]);117}118119private static String keywordValue(String[] args, String keyword) {120for (String arg : args)121if (arg.startsWith(keyword))122return arg.substring(keyword.length() + 1);123return null;124}125126private static int intArg(String[] args, String keyword, int defaultValue) {127String val = keywordValue(args, keyword);128return val == null ? defaultValue : Integer.parseInt(val);129}130131private static Pattern patternArg(String[] args, String keyword) {132String val = keywordValue(args, keyword);133return val == null ? null : Pattern.compile(val);134}135136private static Job[] filter(Pattern filter, Job[] jobs) {137if (filter == null) return jobs;138Job[] newJobs = new Job[jobs.length];139int n = 0;140for (Job job : jobs)141if (filter.matcher(job.name()).find())142newJobs[n++] = job;143// Arrays.copyOf not available in JDK 5144Job[] ret = new Job[n];145System.arraycopy(newJobs, 0, ret, 0, n);146return ret;147}148149private static void deoptimize(int sum) {150if (sum == 42)151System.out.println("the answer");152}153154private static <T> List<T> asSubList(List<T> list) {155return list.subList(0, list.size());156}157158private static <T> Iterable<T> backwards(final List<T> list) {159return new Iterable<T>() {160public Iterator<T> iterator() {161return new Iterator<T>() {162final ListIterator<T> it = list.listIterator(list.size());163public boolean hasNext() { return it.hasPrevious(); }164public T next() { return it.previous(); }165public void remove() { it.remove(); }};}};166}167168/**169* Usage: [iterations=N] [size=N] [filter=REGEXP]170*/171public static void main(String[] args) throws Throwable {172final int iterations = intArg(args, "iterations", 100000);173final int size = intArg(args, "size", 1000);174final Pattern filter = patternArg(args, "filter");175176final ConcurrentSkipListMap<Integer,Integer> m177= new ConcurrentSkipListMap<Integer,Integer>();178final Vector<Integer> v = new Vector<Integer>(size);179final ArrayList<Integer> al = new ArrayList<Integer>(size);180181// Populate collections with random data182final Random rnd = new Random();183for (int i = 0; i < size; i++) {184m.put(rnd.nextInt(size), rnd.nextInt(size));185v.add(rnd.nextInt(size));186}187al.addAll(v);188189// Also test "short" collections190final int shortSize = 5;191final Vector<Integer> sv = new Vector<Integer>(v.subList(0, shortSize));192final ArrayList<Integer> sal = new ArrayList<Integer>(sv);193194// Checks for correctness *and* prevents loop optimizations195class Check {196private int sum;197public void sum(int sum) {198if (this.sum == 0)199this.sum = sum;200if (this.sum != sum)201throw new AssertionError("Sum mismatch");202}203}204final Check check = new Check();205final Check shortCheck = new Check();206207Job[] jobs = {208// new Job("Vector iterate desugared") {209// public void work() throws Throwable {210// for (int i = 0; i < iterations; i++) {211// int sum = 0;212// for (Iterator<Integer> it = v.iterator(); it.hasNext();)213// sum += it.next();214// check.sum(sum);}}},215new Job("array loop") {216public void work() throws Throwable {217Integer[] a = al.toArray(new Integer[0]);218for (int i = 0; i < iterations; i++) {219int sum = 0;220int size = a.length;221for (int j = 0; j < size; ++j)222sum += a[j];223check.sum(sum);}}},224new Job("Vector get loop") {225public void work() throws Throwable {226for (int i = 0; i < iterations; i++) {227int sum = 0;228int size = v.size();229for (int j = 0; j < size; ++j)230sum += v.get(j);231check.sum(sum);}}},232new Job("Vector iterate for loop") {233public void work() throws Throwable {234for (int i = 0; i < iterations; i++) {235int sum = 0;236for (Integer n : v)237sum += n;238check.sum(sum);}}},239new Job("Vector descending listIterator loop") {240public void work() throws Throwable {241for (int i = 0; i < iterations; i++) {242int sum = 0;243ListIterator<Integer> it = v.listIterator(al.size());244while (it.hasPrevious())245sum += it.previous();246check.sum(sum);}}},247new Job("Vector Enumeration loop") {248public void work() throws Throwable {249for (int i = 0; i < iterations; i++) {250int sum = 0;251Enumeration<Integer> it = v.elements();252while (it.hasMoreElements())253sum += it.nextElement();254check.sum(sum);}}},255new Job("Vector subList iterate for loop") {256public void work() throws Throwable {257for (int i = 0; i < iterations; i++) {258int sum = 0;259for (Integer n : asSubList(v))260sum += n;261check.sum(sum);}}},262new Job("Vector subList subList subList iterate for loop") {263public void work() throws Throwable {264for (int i = 0; i < iterations; i++) {265int sum = 0;266for (Integer n : asSubList(asSubList(asSubList(v))))267sum += n;268check.sum(sum);}}},269new Job("Vector backwards wrapper ListIterator for loop") {270public void work() throws Throwable {271for (int i = 0; i < iterations; i++) {272int sum = 0;273for (Integer n : backwards(v))274sum += n;275check.sum(sum);}}},276new Job("Vector backwards wrapper subList ListIterator for loop") {277public void work() throws Throwable {278for (int i = 0; i < iterations; i++) {279int sum = 0;280for (Integer n : backwards(asSubList(v)))281sum += n;282check.sum(sum);}}},283// new Job("Vector iterate for loop invokeinterface") {284// public void work() throws Throwable {285// final List<Integer> l = v;286// for (int i = 0; i < iterations; i++) {287// int sum = 0;288// for (Integer n : l)289// sum += n;290// check.sum(sum);}}},291// new Job("Vector subList iterate for loop invokeinterface") {292// public void work() throws Throwable {293// final List<Integer> l = v;294// for (int i = 0; i < iterations; i++) {295// int sum = 0;296// for (Integer n : asSubList(l))297// sum += n;298// check.sum(sum);}}},299new Job("Short Vector get loop") {300public void work() throws Throwable {301for (int i = 0; i < (iterations * size / shortSize); i++) {302int sum = 0;303int size = sv.size();304for (int j = 0; j < size; ++j)305sum += sv.get(j);306shortCheck.sum(sum);}}},307new Job("Short Vector iterate for loop") {308public void work() throws Throwable {309for (int i = 0; i < (iterations * size / shortSize); i++) {310int sum = 0;311for (Integer n : sv)312sum += n;313shortCheck.sum(sum);}}},314new Job("Short Vector sublist iterate for loop") {315public void work() throws Throwable {316for (int i = 0; i < (iterations * size / shortSize); i++) {317int sum = 0;318for (Integer n : asSubList(sv))319sum += n;320shortCheck.sum(sum);}}},321new Job("ArrayList get loop") {322public void work() throws Throwable {323for (int i = 0; i < iterations; i++) {324int sum = 0;325int size = al.size();326for (int j = 0; j < size; ++j)327sum += al.get(j);328check.sum(sum);}}},329new Job("ArrayList iterate for loop") {330public void work() throws Throwable {331for (int i = 0; i < iterations; i++) {332int sum = 0;333for (Integer n : al)334sum += n;335check.sum(sum);}}},336new Job("ArrayList descending listIterator loop") {337public void work() throws Throwable {338for (int i = 0; i < iterations; i++) {339int sum = 0;340ListIterator<Integer> it = al.listIterator(al.size());341while (it.hasPrevious())342sum += it.previous();343check.sum(sum);}}},344new Job("ArrayList listIterator loop") {345public void work() throws Throwable {346for (int i = 0; i < iterations; i++) {347int sum = 0;348ListIterator<Integer> it = al.listIterator();349while (it.hasNext())350sum += it.next();351check.sum(sum);}}},352new Job("ArrayList subList get loop") {353public void work() throws Throwable {354List<Integer> sl = asSubList(al);355for (int i = 0; i < iterations; i++) {356int sum = 0;357int size = sl.size();358for (int j = 0; j < size; ++j)359sum += sl.get(j);360check.sum(sum);}}},361new Job("ArrayList subList iterate for loop") {362public void work() throws Throwable {363for (int i = 0; i < iterations; i++) {364int sum = 0;365for (Integer n : asSubList(al))366sum += n;367check.sum(sum);}}},368new Job("ArrayList subList subList subList iterate for loop") {369public void work() throws Throwable {370for (int i = 0; i < iterations; i++) {371int sum = 0;372for (Integer n : asSubList(asSubList(asSubList(al))))373sum += n;374check.sum(sum);}}},375new Job("ArrayList backwards wrapper ListIterator for loop") {376public void work() throws Throwable {377for (int i = 0; i < iterations; i++) {378int sum = 0;379for (Integer n : backwards(al))380sum += n;381check.sum(sum);}}},382new Job("ArrayList backwards wrapper subList ListIterator for loop") {383public void work() throws Throwable {384for (int i = 0; i < iterations; i++) {385int sum = 0;386for (Integer n : backwards(asSubList(al)))387sum += n;388check.sum(sum);}}},389// new Job("ArrayList iterate desugared") {390// public void work() throws Throwable {391// for (int i = 0; i < iterations; i++) {392// int sum = 0;393// for (Iterator<Integer> it = al.iterator(); it.hasNext();)394// sum += it.next();395// check.sum(sum);}}},396new Job("Short ArrayList get loop") {397public void work() throws Throwable {398for (int i = 0; i < (iterations * size / shortSize); i++) {399int sum = 0;400int size = sal.size();401for (int j = 0; j < size; ++j)402sum += sal.get(j);403shortCheck.sum(sum);}}},404new Job("Short ArrayList iterate for loop") {405public void work() throws Throwable {406for (int i = 0; i < (iterations * size / shortSize); i++) {407int sum = 0;408for (Integer n : sal)409sum += n;410shortCheck.sum(sum);}}},411new Job("Short ArrayList sublist iterate for loop") {412public void work() throws Throwable {413for (int i = 0; i < (iterations * size / shortSize); i++) {414int sum = 0;415for (Integer n : asSubList(sal))416sum += n;417shortCheck.sum(sum);}}},418new Job("Vector ArrayList alternating iteration") {419public void work() throws Throwable {420for (int i = 0; i < iterations; i++) {421int sum = 0;422Iterator<Integer> it1 = v.iterator();423Iterator<Integer> it2 = al.iterator();424while (it1.hasNext())425sum += it1.next() + it2.next();426check.sum(sum/2);}}},427new Job("Vector ArrayList alternating invokeVirtual iteration") {428public void work() throws Throwable {429for (int i = 0; i < iterations; i++) {430int sum = 0;431List<Iterator<Integer>> its432= new ArrayList<Iterator<Integer>>(2);433its.add(v.iterator());434its.add(al.iterator());435for (int k = 0; its.get(k).hasNext(); k = (k == 0) ? 1 : 0)436sum += its.get(k).next();437check.sum(sum/2);}}},438new Job("ConcurrentSkipListMap entrySet iterate") {439public void work() throws Throwable {440for (int i = 0; i < iterations; i++) {441int sum = 0;442for (Map.Entry<Integer,Integer> e : m.entrySet())443sum += e.getKey();444deoptimize(sum);}}}445};446447time(filter(filter, jobs));448}449}450451452