36
36
import java .util .Collection ;
37
37
import java .util .Collections ;
38
38
import java .util .Deque ;
39
+ import java .util .HashMap ;
39
40
import java .util .Iterator ;
40
41
import java .util .LinkedList ;
41
42
import java .util .List ;
55
56
import java .util .concurrent .ThreadLocalRandom ;
56
57
import java .util .concurrent .TimeUnit ;
57
58
import java .util .concurrent .atomic .LongAdder ;
59
+ import java .util .function .UnaryOperator ;
58
60
import java .util .regex .Pattern ;
59
61
import java .util .stream .Stream ;
60
62
@@ -75,6 +77,13 @@ abstract static class Job {
75
77
public Job (String name ) { this .name = name ; }
76
78
public String name () { return name ; }
77
79
public abstract void work () throws Throwable ;
80
+ public void run () {
81
+ try { work (); }
82
+ catch (Throwable ex ) {
83
+ // current job cannot always be deduced from stacktrace.
84
+ throw new RuntimeException ("Job failed: " + name (), ex );
85
+ }
86
+ }
78
87
}
79
88
80
89
final int iterations ;
@@ -102,6 +111,7 @@ abstract static class Job {
102
111
static void forceFullGc () {
103
112
CountDownLatch finalizeDone = new CountDownLatch (1 );
104
113
WeakReference <?> ref = new WeakReference <Object >(new Object () {
114
+ @ SuppressWarnings ("deprecation" )
105
115
protected void finalize () { finalizeDone .countDown (); }});
106
116
try {
107
117
for (int i = 0 ; i < 10 ; i ++) {
@@ -123,7 +133,7 @@ static void forceFullGc() {
123
133
* compiling everything worth compiling.
124
134
* Returns array of average times per job per run.
125
135
*/
126
- long [] time0 (List <Job > jobs ) throws Throwable {
136
+ long [] time0 (List <Job > jobs ) {
127
137
final int size = jobs .size ();
128
138
long [] nanoss = new long [size ];
129
139
for (int i = 0 ; i < size ; i ++) {
@@ -132,7 +142,7 @@ long[] time0(List<Job> jobs) throws Throwable {
132
142
long totalTime ;
133
143
int runs = 0 ;
134
144
long startTime = System .nanoTime ();
135
- do { job .work (); runs ++; }
145
+ do { job .run (); runs ++; }
136
146
while ((totalTime = System .nanoTime () - startTime ) < warmupNanos );
137
147
nanoss [i ] = totalTime /runs ;
138
148
}
@@ -211,10 +221,6 @@ private static void deoptimize(int sum) {
211
221
System .out .println ("the answer" );
212
222
}
213
223
214
- private static <T > List <T > asSubList (List <T > list ) {
215
- return list .subList (0 , list .size ());
216
- }
217
-
218
224
private static <T > Iterable <T > backwards (final List <T > list ) {
219
225
return new Iterable <T >() {
220
226
public Iterator <T > iterator () {
@@ -241,11 +247,32 @@ public static void main(String[] args) throws Throwable {
241
247
new IteratorMicroBenchmark (args ).run ();
242
248
}
243
249
244
- void run () throws Throwable {
245
- // System.out.printf(
246
- // "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n",
247
- // iterations, size, warmupSeconds, nameFilter);
250
+ HashMap <Class <?>, String > goodClassName = new HashMap <>();
251
+
252
+ String goodClassName (Class <?> klazz ) {
253
+ return goodClassName .computeIfAbsent (
254
+ klazz ,
255
+ k -> {
256
+ String simple = k .getSimpleName ();
257
+ return (simple .equals ("SubList" )) // too simple!
258
+ ? k .getName ().replaceFirst (".*\\ ." , "" )
259
+ : simple ;
260
+ });
261
+ }
248
262
263
+ static List <Integer > makeSubList (List <Integer > list ) {
264
+ final ThreadLocalRandom rnd = ThreadLocalRandom .current ();
265
+ int size = list .size ();
266
+ if (size <= 2 ) return list .subList (0 , size );
267
+ List <Integer > subList = list .subList (rnd .nextInt (0 , 2 ),
268
+ size - rnd .nextInt (0 , 2 ));
269
+ List <Integer > copy = new ArrayList <>(list );
270
+ subList .clear ();
271
+ subList .addAll (copy );
272
+ return subList ;
273
+ }
274
+
275
+ void run () throws Throwable {
249
276
final ArrayList <Integer > al = new ArrayList <>(size );
250
277
251
278
// Populate collections with random data
@@ -265,10 +292,14 @@ void run() throws Throwable {
265
292
266
293
ArrayList <Job > jobs = Stream .<Collection <Integer >>of (
267
294
al , ad , abq ,
295
+ makeSubList (new ArrayList <>(al )),
268
296
new LinkedList <>(al ),
297
+ makeSubList (new LinkedList <>(al )),
269
298
new PriorityQueue <>(al ),
270
299
new Vector <>(al ),
300
+ makeSubList (new Vector <>(al )),
271
301
new CopyOnWriteArrayList <>(al ),
302
+ makeSubList (new CopyOnWriteArrayList <>(al )),
272
303
new ConcurrentLinkedQueue <>(al ),
273
304
new ConcurrentLinkedDeque <>(al ),
274
305
new LinkedBlockingQueue <>(al ),
@@ -294,16 +325,25 @@ private <T> Stream<T> concatStreams(Stream<T> ... streams) {
294
325
Stream <Job > jobs (Collection <Integer > x ) {
295
326
return concatStreams (
296
327
collectionJobs (x ),
328
+
297
329
(x instanceof Deque )
298
330
? dequeJobs ((Deque <Integer >)x )
299
331
: Stream .empty (),
332
+
300
333
(x instanceof List )
301
334
? listJobs ((List <Integer >)x )
302
335
: Stream .empty ());
303
336
}
304
337
338
+ Object sneakyAdder (int [] sneakySum ) {
339
+ return new Object () {
340
+ public int hashCode () { throw new AssertionError (); }
341
+ public boolean equals (Object z ) {
342
+ sneakySum [0 ] += (int ) z ; return false ; }};
343
+ }
344
+
305
345
Stream <Job > collectionJobs (Collection <Integer > x ) {
306
- String klazz = x .getClass (). getSimpleName ( );
346
+ final String klazz = goodClassName ( x .getClass ());
307
347
return Stream .of (
308
348
new Job (klazz + " iterate for loop" ) {
309
349
public void work () throws Throwable {
@@ -345,22 +385,28 @@ public void work() throws Throwable {
345
385
new Job (klazz + " contains" ) {
346
386
public void work () throws Throwable {
347
387
int [] sum = new int [1 ];
348
- Object y = new Object () {
349
- public boolean equals (Object z ) {
350
- sum [0 ] += (int ) z ; return false ; }};
388
+ Object sneakyAdder = sneakyAdder (sum );
389
+ for (int i = 0 ; i < iterations ; i ++) {
390
+ sum [0 ] = 0 ;
391
+ if (x .contains (sneakyAdder )) throw new AssertionError ();
392
+ check .sum (sum [0 ]);}}},
393
+ new Job (klazz + " containsAll" ) {
394
+ public void work () throws Throwable {
395
+ int [] sum = new int [1 ];
396
+ Collection <Object > sneakyAdderCollection =
397
+ Collections .singleton (sneakyAdder (sum ));
351
398
for (int i = 0 ; i < iterations ; i ++) {
352
399
sum [0 ] = 0 ;
353
- if (x .contains (y )) throw new AssertionError ();
400
+ if (x .containsAll (sneakyAdderCollection ))
401
+ throw new AssertionError ();
354
402
check .sum (sum [0 ]);}}},
355
403
new Job (klazz + " remove(Object)" ) {
356
404
public void work () throws Throwable {
357
405
int [] sum = new int [1 ];
358
- Object y = new Object () {
359
- public boolean equals (Object z ) {
360
- sum [0 ] += (int ) z ; return false ; }};
406
+ Object sneakyAdder = sneakyAdder (sum );
361
407
for (int i = 0 ; i < iterations ; i ++) {
362
408
sum [0 ] = 0 ;
363
- if (x .remove (y )) throw new AssertionError ();
409
+ if (x .remove (sneakyAdder )) throw new AssertionError ();
364
410
check .sum (sum [0 ]);}}},
365
411
new Job (klazz + " forEach" ) {
366
412
public void work () throws Throwable {
@@ -446,7 +492,7 @@ public void work() throws Throwable {
446
492
}
447
493
448
494
Stream <Job > dequeJobs (Deque <Integer > x ) {
449
- String klazz = x .getClass (). getSimpleName ( );
495
+ String klazz = goodClassName ( x .getClass ());
450
496
return Stream .of (
451
497
new Job (klazz + " descendingIterator() loop" ) {
452
498
public void work () throws Throwable {
@@ -466,48 +512,50 @@ public void work() throws Throwable {
466
512
}
467
513
468
514
Stream <Job > listJobs (List <Integer > x ) {
469
- String klazz = x .getClass (). getSimpleName ( );
515
+ final String klazz = goodClassName ( x .getClass ());
470
516
return Stream .of (
471
- new Job (klazz + " subList toArray()" ) {
517
+ new Job (klazz + " listIterator forward loop" ) {
518
+ public void work () throws Throwable {
519
+ for (int i = 0 ; i < iterations ; i ++) {
520
+ int sum = 0 ;
521
+ ListIterator <Integer > it = x .listIterator ();
522
+ while (it .hasNext ())
523
+ sum += it .next ();
524
+ check .sum (sum );}}},
525
+ new Job (klazz + " listIterator backward loop" ) {
472
526
public void work () throws Throwable {
473
- int size = x .size ();
474
527
for (int i = 0 ; i < iterations ; i ++) {
475
- int total = Stream .of (x .subList (0 , size / 2 ),
476
- x .subList (size / 2 , size ))
477
- .mapToInt (subList -> {
478
- int sum = 0 ;
479
- for (Object o : subList .toArray ())
480
- sum += (Integer ) o ;
481
- return sum ; })
482
- .sum ();
483
- check .sum (total );}}},
484
- new Job (klazz + " subList toArray(a)" ) {
528
+ int sum = 0 ;
529
+ ListIterator <Integer > it = x .listIterator (x .size ());
530
+ while (it .hasPrevious ())
531
+ sum += it .previous ();
532
+ check .sum (sum );}}},
533
+ new Job (klazz + " indexOf" ) {
485
534
public void work () throws Throwable {
486
- int size = x .size ();
535
+ int [] sum = new int [1 ];
536
+ Object sneakyAdder = sneakyAdder (sum );
487
537
for (int i = 0 ; i < iterations ; i ++) {
488
- int total = Stream .of (x .subList (0 , size / 2 ),
489
- x .subList (size / 2 , size ))
490
- .mapToInt (subList -> {
491
- int sum = 0 ;
492
- Integer [] a = new Integer [subList .size ()];
493
- for (Object o : subList .toArray (a ))
494
- sum += (Integer ) o ;
495
- return sum ; })
496
- .sum ();
497
- check .sum (total );}}},
498
- new Job (klazz + " subList toArray(empty)" ) {
538
+ sum [0 ] = 0 ;
539
+ if (x .indexOf (sneakyAdder ) != -1 )
540
+ throw new AssertionError ();
541
+ check .sum (sum [0 ]);}}},
542
+ new Job (klazz + " lastIndexOf" ) {
499
543
public void work () throws Throwable {
500
- int size = x .size ();
501
- Integer [] empty = new Integer [0 ];
544
+ int [] sum = new int [1 ];
545
+ Object sneakyAdder = sneakyAdder (sum );
546
+ for (int i = 0 ; i < iterations ; i ++) {
547
+ sum [0 ] = 0 ;
548
+ if (x .lastIndexOf (sneakyAdder ) != -1 )
549
+ throw new AssertionError ();
550
+ check .sum (sum [0 ]);}}},
551
+ new Job (klazz + " replaceAll" ) {
552
+ public void work () throws Throwable {
553
+ int [] sum = new int [1 ];
554
+ UnaryOperator <Integer > sneakyAdder =
555
+ x -> { sum [0 ] += x ; return x ; };
502
556
for (int i = 0 ; i < iterations ; i ++) {
503
- int total = Stream .of (x .subList (0 , size / 2 ),
504
- x .subList (size / 2 , size ))
505
- .mapToInt (subList -> {
506
- int sum = 0 ;
507
- for (Object o : subList .toArray (empty ))
508
- sum += (Integer ) o ;
509
- return sum ; })
510
- .sum ();
511
- check .sum (total );}}});
557
+ sum [0 ] = 0 ;
558
+ x .replaceAll (sneakyAdder );
559
+ check .sum (sum [0 ]);}}});
512
560
}
513
561
}
0 commit comments