1 /* 2 * Copyright (c) 2014 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package org.openjdk.bench.java.util.concurrent; 26 27 import org.openjdk.jmh.annotations.Benchmark; 28 import org.openjdk.jmh.annotations.OutputTimeUnit; 29 import org.openjdk.jmh.annotations.Param; 30 import org.openjdk.jmh.annotations.Scope; 31 import org.openjdk.jmh.annotations.Setup; 32 import org.openjdk.jmh.annotations.State; 33 import org.openjdk.jmh.annotations.TearDown; 34 35 import java.util.concurrent.ExecutionException; 36 import java.util.concurrent.ForkJoinPool; 37 import java.util.concurrent.ForkJoinTask; 38 import java.util.concurrent.RecursiveTask; 39 import java.util.concurrent.TimeUnit; 40 41 /** 42 * Benchmark assesses ForkJoinPool performance with dependence on threshold. 43 */ 44 @OutputTimeUnit(TimeUnit.MINUTES) 45 @State(Scope.Benchmark) 46 public class ForkJoinPoolThresholdStatic { 47 48 /** 49 * Implementation notes: 50 * 51 * This test solves the problem on different threshold levels. 52 * The optimal level depends on available parallelism. 53 * Lower thresholds will suffer because of ForkJoinPool infrastructure overheads. 54 * Higher thresholds will suffer because of lower available task parallelism. 55 * 56 * Baseline includes solving problem sequentially. 57 * Hence, each test provides the speedup for parallel execution 58 * versus sequential version. 59 */ 60 61 @Param("0") 62 private int workers; 63 64 @Param("10000000") 65 private int size; 66 67 @Param({"1", "5", "10", "50", "100", "500", "1000", "5000", "10000", "50000", "100000", "500000", "1000000", "5000000", "10000000"}) 68 private int threshold; 69 70 private ForkJoinPool fjp; 71 private Problem problem; 72 73 @Setup 74 public void setup() { 75 if (workers == 0) { 76 workers = Runtime.getRuntime().availableProcessors(); 77 } 78 79 problem = new Problem(size); 80 fjp = new ForkJoinPool(workers); 81 } 82 83 @TearDown 84 public void teardown() { 85 fjp.shutdownNow(); 86 } 87 88 @Benchmark 89 public long baselineRaw() { 90 return problem.solve(); 91 } 92 93 @Benchmark 94 public Long test() throws ExecutionException, InterruptedException { 95 return fjp.invoke(new AdjustableThreshTask(threshold, problem, 0, problem.size())); 96 } 97 98 private static class AdjustableThreshTask extends RecursiveTask<Long> { 99 private final int thr; 100 private final Problem problem; 101 private final int l; 102 private final int r; 103 104 public AdjustableThreshTask(int thr, Problem p, int l, int r) { 105 this.thr = thr; 106 this.problem = p; 107 this.l = l; 108 this.r = r; 109 } 110 111 @Override 112 protected Long compute() { 113 if (r - l <= thr) { 114 return problem.solve(l, r); 115 } 116 117 int mid = (l + r) >>> 1; 118 ForkJoinTask<Long> t1 = new AdjustableThreshTask(thr, problem, l, mid); 119 ForkJoinTask<Long> t2 = new AdjustableThreshTask(thr, problem, mid, r); 120 121 ForkJoinTask.invokeAll(t1, t2); 122 123 long res = 0; 124 res += t1.join(); 125 res += t2.join(); 126 return res; 127 } 128 } 129 130 131 }