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