Crossfire JXClient, Trunk
MergeDemo.java
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of Oracle nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * This source code is provided to illustrate the usage of a given feature
34  * or technique and has been deliberately simplified. Additional steps
35  * required for a production-quality application, such as security checks,
36  * input validation and proper error handling, might not be present in
37  * this sample code.
38  */
39 
40 
41 import java.util.Arrays;
42 import java.util.Random;
43 
44 import static java.lang.Integer.parseInt;
45 
54 public class MergeDemo {
55  // Use a fixed seed to always get the same random values back
56  private final Random random = new Random(759123751834L);
57  private static final int ITERATIONS = 10;
58 
62  private static class Range {
63  private final int start;
64  private final int step;
65  private final int iterations;
66 
67  private Range(int start, int step, int iterations) {
68  this.start = start;
69  this.step = step;
70  this.iterations = iterations;
71  }
72 
79  public static Range parse(String[] args, int start) {
80  if (args.length < start + 3) {
81  throw new IllegalArgumentException("Too few elements in array");
82  }
83  return new Range(parseInt(args[start]), parseInt(args[start + 1]), parseInt(args[start + 2]));
84  }
85 
86  public int get(int iteration) {
87  return start + (step * iteration);
88  }
89 
90  public int getIterations() {
91  return iterations;
92  }
93 
94  @Override
95  public String toString() {
96  StringBuilder builder = new StringBuilder();
97  builder.append(start).append(" ").append(step).append(" ").append(iterations);
98  return builder.toString();
99  }
100  }
101 
107  private static class Configuration {
108  private final Range sizes;
109  private final Range parallelism;
110 
111  private final static Configuration defaultConfig = new Configuration(new Range(20000, 20000, 10),
112  new Range(2, 2, 10));
113 
115  this.sizes = sizes;
116  this.parallelism = parallelism;
117  }
118 
125  public static Configuration parse(String[] args) {
126  if (args.length == 0) {
127  return defaultConfig;
128  } else {
129  try {
130  if (args.length == 6) {
131  return new Configuration(Range.parse(args, 0), Range.parse(args, 3));
132  }
133  } catch (NumberFormatException e) {
134  System.err.println("MergeExample: error: Argument was not a number.");
135  }
136  System.err.println("MergeExample <size start> <size step> <size steps> <parallel start> <parallel step>" +
137  " <parallel steps>");
138  System.err.println("example: MergeExample 20000 10000 3 1 1 4");
139  System.err.println("example: will run with arrays of sizes 20000, 30000, 40000" +
140  " and parallelism: 1, 2, 3, 4");
141  return null;
142  }
143  }
144 
149  private long[][] createTimesArray() {
150  return new long[sizes.getIterations()][parallelism.getIterations()];
151  }
152 
153  @Override
154  public String toString() {
155  StringBuilder builder = new StringBuilder("");
156  if (this == defaultConfig) {
157  builder.append("Default configuration. ");
158  }
159  builder.append("Running with parameters: ");
160  builder.append(sizes);
161  builder.append(" ");
162  builder.append(parallelism);
163  return builder.toString();
164  }
165  }
166 
172  private int[] generateArray(int elements) {
173  int[] array = new int[elements];
174  for (int i = 0; i < elements; ++i) {
175  array[i] = random.nextInt();
176  }
177  return array;
178  }
179 
184  private void run(Configuration config) {
185  Range sizes = config.sizes;
186  Range parallelism = config.parallelism;
187 
188  // Run a couple of sorts to make the JIT compile / optimize the code
189  // which should produce somewhat more fair times
190  warmup();
191 
192  long[][] times = config.createTimesArray();
193 
194  for (int size = 0; size < sizes.getIterations(); size++) {
195  runForSize(parallelism, sizes.get(size), times, size);
196  }
197 
198  printResults(sizes, parallelism, times);
199  }
200 
207  private void printResults(Range sizes, Range parallelism, long[][] times) {
208  System.out.println("Time in milliseconds. Y-axis: number of elements. X-axis parallelism used.");
209  long[] sums = new long[times[0].length];
210  System.out.format("%8s ", "");
211  for (int i = 0; i < times[0].length; i++) {
212  System.out.format("%4d ", parallelism.get(i));
213  }
214  System.out.println("");
215  for (int size = 0; size < sizes.getIterations(); size++) {
216  System.out.format("%8d: ", sizes.get(size));
217  for (int i = 0; i < times[size].length; i++) {
218  sums[i] += times[size][i];
219  System.out.format("%4d ", times[size][i]);
220  }
221  System.out.println("");
222  }
223  System.out.format("%8s: ", "Total");
224  for (long sum : sums) {
225  System.out.format("%4d ", sum);
226  }
227  System.out.println("");
228  }
229 
230  private void runForSize(Range parallelism, int elements, long[][] times, int size) {
231  for (int step = 0; step < parallelism.getIterations(); step++) {
232  long time = runForParallelism(ITERATIONS, elements, parallelism.get(step));
233  times[size][step] = time;
234  }
235  }
236 
244  private long runForParallelism(int iterations, int elements, int parallelism) {
245  MergeSort mergeSort = new MergeSort(parallelism);
246  long[] times = new long[iterations];
247 
248  for (int i = 0; i < iterations; i++) {
249  // Suggest the VM to run a garbage collection to reduce the risk of getting one
250  // while running the test run
251  System.gc();
252  long start = System.currentTimeMillis();
253  mergeSort.sort(generateArray(elements));
254  times[i] = System.currentTimeMillis() - start;
255  }
256 
257  return medianValue(times);
258  }
259 
265  private long medianValue(long[] times) {
266  if (times.length == 0) {
267  throw new IllegalArgumentException("Empty array");
268  }
269  // Make a copy of times to avoid having side effects on the parameter value
270  Arrays.sort(times.clone());
271  long median = times[times.length / 2];
272  if (times.length > 1 && times.length % 2 != 0) {
273  median = (median + times[times.length / 2 + 1]) / 2;
274  }
275  return median;
276  }
277 
281  private void warmup() {
282  MergeSort mergeSort = new MergeSort(Runtime.getRuntime().availableProcessors());
283  for (int i = 0; i < 1000; i++) {
284  mergeSort.sort(generateArray(1000));
285  }
286  }
287 
288  public static void main(String[] args) {
289  Configuration configuration = Configuration.parse(args);
290  if (configuration == null) {
291  System.exit(1);
292  }
293  System.out.println(configuration);
294  new MergeDemo().run(configuration);
295  }
296 }
MergeDemo.Configuration.sizes
final Range sizes
Definition: MergeDemo.java:108
MergeDemo.runForParallelism
long runForParallelism(int iterations, int elements, int parallelism)
Definition: MergeDemo.java:244
MergeDemo
Definition: MergeDemo.java:54
MergeDemo.Range.iterations
final int iterations
Definition: MergeDemo.java:65
MergeDemo.Range.toString
String toString()
Definition: MergeDemo.java:95
MergeDemo.Range.parse
static Range parse(String[] args, int start)
Definition: MergeDemo.java:79
MergeDemo.Range.getIterations
int getIterations()
Definition: MergeDemo.java:90
MergeDemo.Configuration.createTimesArray
long[][] createTimesArray()
Definition: MergeDemo.java:149
MergeDemo.Configuration.parallelism
final Range parallelism
Definition: MergeDemo.java:109
MergeDemo.main
static void main(String[] args)
Definition: MergeDemo.java:288
MergeDemo.generateArray
int[] generateArray(int elements)
Definition: MergeDemo.java:172
MergeDemo.Configuration.parse
static Configuration parse(String[] args)
Definition: MergeDemo.java:125
MergeDemo.warmup
void warmup()
Definition: MergeDemo.java:281
MergeDemo.Configuration
Definition: MergeDemo.java:107
MergeDemo.Range.Range
Range(int start, int step, int iterations)
Definition: MergeDemo.java:67
MergeDemo.medianValue
long medianValue(long[] times)
Definition: MergeDemo.java:265
MergeDemo.printResults
void printResults(Range sizes, Range parallelism, long[][] times)
Definition: MergeDemo.java:207
MergeSort
Definition: MergeSort.java:62
MergeDemo.Range.step
final int step
Definition: MergeDemo.java:64
MergeDemo.random
final Random random
Definition: MergeDemo.java:56
MergeDemo.run
void run(Configuration config)
Definition: MergeDemo.java:184
MergeDemo.runForSize
void runForSize(Range parallelism, int elements, long[][] times, int size)
Definition: MergeDemo.java:230
MergeDemo.Range
Definition: MergeDemo.java:62
MergeDemo.Configuration.toString
String toString()
Definition: MergeDemo.java:154
MergeDemo.Configuration.defaultConfig
static final Configuration defaultConfig
Definition: MergeDemo.java:111
MergeDemo.Range.get
int get(int iteration)
Definition: MergeDemo.java:86
MergeDemo.ITERATIONS
static final int ITERATIONS
Definition: MergeDemo.java:57
MergeDemo.Range.start
final int start
Definition: MergeDemo.java:63
MergeSort.sort
void sort(int[] array)
Definition: MergeSort.java:133
MergeDemo.Configuration.Configuration
Configuration(Range sizes, Range parallelism)
Definition: MergeDemo.java:114