ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/MapMicroBenchmark.java
(Generate patch)

Comparing jsr166/src/test/loops/MapMicroBenchmark.java (file contents):
Revision 1.2 by dl, Wed Jul 22 16:19:51 2009 UTC vs.
Revision 1.3 by dl, Sun Jul 26 15:40:47 2009 UTC

# Line 5 | Line 5
5   */
6  
7   import java.util.*;
8 + import java.io.*;
9   import java.math.*;
10  
11   /**
# Line 25 | Line 26 | import java.math.*;
26   * but because they can be problematic for some map implementations.
27   *
28   * By default, it creates and inserts in order dense numerical keys
29 < * and searches for keys in scrambled order. Use "r" as second arg to
30 < * instead use random numerical values, and "s" as third arg to search
31 < * in insertion order.
29 > * and searches for keys in scrambled order. Use "s" as second arg to
30 > * instead insert and search in unscrambled order.
31 > *
32 > * For String keys, the program tries to use file "testwords.txt", which
33 > * is best used with real words.  We can't check in this file, but you
34 > * can create one from a real dictonary (1 line per word) and then run
35 > * linux "shuf" to randomize entries. If no file exists, it uses
36 > * String.valueOf(i) for element i.
37   */
38   public class MapMicroBenchmark {
39 +    static final String wordFile = "testwords.txt";
40 +
41      static Class mapClass;
42      static boolean randomSearches = true;
35    static boolean randomKeys = false;
43  
44      // Nanoseconds per run
45      static final long NANOS_PER_JOB = 6L * 1000L*1000L*1000L;
# Line 40 | Line 47 | public class MapMicroBenchmark {
47  
48      // map operations per item per iteration -- change if job.work changed
49      static final int OPS_PER_ITER = 11;
50 <    static final int MIN_ITERS_PER_TEST = 3;
50 >    static final int MIN_ITERS_PER_TEST = 3; // must be > 1
51      static final int MAX_ITERS_PER_TEST = 1000000; // avoid runaway
52  
53      // sizes are at halfway points for HashMap default resizes
# Line 59 | Line 66 | public class MapMicroBenchmark {
66  
67          if (args.length > 1) {
68              if (args[1].startsWith("s"))
62                randomKeys = false;
63            else if (args[1].startsWith("r"))
64                randomKeys = true;
65        }
66        if (args.length > 2) {
67            if (args[2].startsWith("s"))
69                  randomSearches = false;
70 <            else if (args[2].startsWith("r"))
70 >            else if (args[1].startsWith("r"))
71                  randomSearches = true;
72          }
73  
74          System.out.print("Class " + mapClass.getName());
74        if (randomKeys)
75            System.out.print(" random keys");
76        else
77            System.out.print(" sequential keys");
75          if (randomSearches)
76              System.out.print(" randomized searches");
77          else
# Line 89 | Line 86 | public class MapMicroBenchmark {
86          }
87          sizes[nsizes - 1] = n;
88  
89 <        int njobs = 9;
89 >        int njobs = 10;
90 >        Job[] jobs = new Job[njobs];
91  
92          Object[] os = new Object[n];
93 <        Object[] ss = new Object[n];
96 <        Object[] is = new Object[n];
97 <        Object[] ls = new Object[n];
98 <        Object[] fs = new Object[n];
99 <        Object[] ds = new Object[n];
100 <        Object[] bs = new Object[n];
101 <        Object[] es = new Object[n];
102 <        Object[] ms = new Object[n];
103 <
104 <        for (int i = 0; i < n; i++) {
105 <            os[i] = new Object();
106 <        }
107 <
108 <        // To guarantee uniqueness, use xorshift for "random" versions
109 <        int rnd = 3122688;
110 <        for (int i = 0; i < n; i++) {
111 <            rnd = xorshift(rnd);
112 <            int j = randomKeys? rnd : i;
113 <            ss[i] = String.valueOf(j);
114 <        }
115 <
116 <        for (int i = 0; i < n; i++) {
117 <            rnd = xorshift(rnd);
118 <            int j = randomKeys? rnd : i;
119 <            is[i] = Integer.valueOf(j);
120 <        }
121 <
122 <        for (int i = 0; i < n; i++) {
123 <            rnd = xorshift(rnd);
124 <            int j = randomKeys? rnd : i;
125 <            ls[i] = Long.valueOf((long)j);
126 <        }
127 <
128 <        for (int i = 0; i < n; i++) {
129 <            //            rnd = xorshift(rnd);
130 <            //            int j = randomKeys? rnd : i;
131 <            fs[i] = Float.valueOf((float)i); // can't use random for float
132 <        }
133 <
134 <        for (int i = 0; i < n; i++) {
135 <            rnd = xorshift(rnd);
136 <            int j = randomKeys? rnd : i;
137 <            ds[i] = Double.valueOf((double)j);
138 <        }
139 <
140 <        for (int i = 0; i < n; i++) {
141 <            rnd = xorshift(rnd);
142 <            int j = randomKeys? rnd : i;
143 <            bs[i] = BigInteger.valueOf(j);
144 <        }
145 <
146 <        for (int i = 0; i < n; i++) {
147 <            rnd = xorshift(rnd);
148 <            int j = randomKeys? rnd : i;
149 <            es[i] = BigDecimal.valueOf(j);
150 <        }
151 <
152 <        Job[] jobs = new Job[njobs];
93 >        for (int i = 0; i < n; i++) os[i] = new Object();
94          jobs[0] = new Job("Object    ", os, Object.class);
95 +
96 +        Object[] ss = new Object[n];
97 +        initStringKeys(ss, n);
98          jobs[1] = new Job("String    ", ss, String.class);
99 +
100 +        Object[] is = new Object[n];
101 +        for (int i = 0; i < n; i++) is[i] = Integer.valueOf(i);
102          jobs[2] = new Job("Integer   ", is, Integer.class);
103 +
104 +        Object[] ls = new Object[n];
105 +        for (int i = 0; i < n; i++) ls[i] = Long.valueOf((long)i);
106          jobs[3] = new Job("Long      ", ls, Long.class);
107 +
108 +        Object[] fs = new Object[n];
109 +        for (int i = 0; i < n; i++) fs[i] = Float.valueOf((float)i);
110          jobs[4] = new Job("Float     ", fs, Float.class);
111 +
112 +        Object[] ds = new Object[n];
113 +        for (int i = 0; i < n; i++) ds[i] = Double.valueOf((double)i);
114          jobs[5] = new Job("Double    ", ds, Double.class);
115 +
116 +        Object[] bs = new Object[n];
117 +        long b = -n; // include some negatives
118 +        for (int i = 0; i < n; i++) bs[i] = BigInteger.valueOf(b += 3);
119          jobs[6] = new Job("BigInteger", bs, BigInteger.class);
120 +
121 +        Object[] es = new Object[n];
122 +        long d = Integer.MAX_VALUE; // include crummy codes
123 +        for (int i = 0; i < n; i++) es[i] = BigDecimal.valueOf(d += 65536);
124          jobs[7] = new Job("BigDecimal", es, BigDecimal.class);
125  
126 <        for (int i = 0; i < n; i +=2) {
127 <            rnd = xorshift(rnd);
128 <            int j = (rnd & 7); // change if njobs changes
165 <            ms[i] = jobs[j].items[i];
166 <            j = (j + 1) & 7;
167 <            ms[i+1] = jobs[j].items[i];
168 <        }
126 >        Object[] rs = new Object[n];
127 >        for (int i = 0; i < n; i++) rs[i] = new RandomInt();
128 >        jobs[8] = new Job("RandomInt ", rs, RandomInt.class);
129  
130 <        jobs[8] = new Job("Mixed     ", ms, Object.class);
130 >        Object[] ms = new Object[n];
131 >        for (int i = 0; i < n; i += 2) {
132 >            int r = rng.nextInt(njobs - 1);
133 >            ms[i] = jobs[r].items[i];
134 >            // include some that will have same hash but not .equal
135 >            if (++r >= njobs - 1) r = 0;
136 >            ms[i+1] = jobs[r].items[i];
137 >        }
138 >        jobs[9] = new Job("Mixed     ", ms, Object.class);
139 >        Job mixed = jobs[9];
140  
141 <        warmup1(jobs[8]);
141 >        warmup1(mixed);
142          warmup2(jobs);
143 <        warmup1(jobs[8]);
143 >        warmup1(mixed);
144          warmup3(jobs);
176        warmup1(jobs[8]);
145          Thread.sleep(500);
146          time(jobs);
147      }
# Line 361 | Line 329 | public class MapMicroBenchmark {
329                      if (m.remove(x) != null)
330                          ++sum;
331                  }
332 +                for (int i = 0; i < quarter; ++i) {
333 +                    Object x = keys[i];
334 +                    if (m.put(x, x) == null)
335 +                        ++sum;
336 +                }
337                  m.clear();
338 <                sum += len - quarter;
338 >                sum += len - (quarter * 2);
339                  checkSum += sum ^ (sum << 12);
340  
341 +                if (j == 0 && sum != lastSum + len * OPS_PER_ITER)
342 +                    throw new Error(name);
343 +                
344                  elapsed = System.nanoTime() - startTime;
345                  ++j;
346                  if (j >= minIters &&
347                      (j >= maxIters || elapsed >= timeLimit))
348                      break;
349 +                // non-warmup - swap some keys for next insert
350 +                if (minIters != 1 && randomSearches)
351 +                    shuffleSome(ins, len, len >>> 3);
352              }
353              long ops = ((long)j) * len * OPS_PER_ITER;
375            if (sum != lastSum + (int)ops)
376                throw new Error(name);
354              lastSum = sum;
355              return elapsed / ops;
356          }
357  
358      }
359  
383    static final int xorshift(int seed) {
384        seed ^= seed << 1;
385        seed ^= seed >>> 3;
386        seed ^= seed << 10;
387        return seed;
388    }
389
360  
361      static final Random rng = new Random(3122688);
362  
# Line 415 | Line 385 | public class MapMicroBenchmark {
385          }
386      }
387  
388 +    // swap nswaps elements
389 +    static void shuffleSome(Object[] a, int size, int nswaps) {
390 +        for (int s = 0; s < nswaps; ++s) {
391 +            int i = rng.nextInt(size);
392 +            int r = rng.nextInt(size);
393 +            Object t = a[i];
394 +            a[i] = a[r];
395 +            a[r] = t;
396 +        }
397 +    }
398 +
399 +    // Integer-like class with random hash codes
400 +    static final class RandomInt {
401 +        static int seed = 3122688;
402 +        static int next() { // a non-xorshift, 2^32-period RNG
403 +            int x = seed;
404 +            int lo = 16807 * (x & 0xFFFF);
405 +            int hi = 16807 * (x >>> 16);
406 +            lo += (hi & 0x7FFF) << 16;
407 +            if ((lo & 0x80000000) != 0) {
408 +                lo &= 0x7fffffff;
409 +                ++lo;
410 +            }
411 +            lo += hi >>> 15;
412 +            if (lo == 0 || (lo & 0x80000000) != 0) {
413 +                lo &= 0x7fffffff;
414 +                ++lo;
415 +            }
416 +            seed = lo;
417 +            return x;
418 +        }
419 +        final int value;
420 +        RandomInt() { value = next(); }
421 +        public int hashCode() { return value; }
422 +        public boolean equals(Object x) {
423 +            return (x instanceof RandomInt) && ((RandomInt)x).value == value;
424 +        }
425 +    }
426  
427 +    // Read in String keys from file if possible
428 +    static void initStringKeys(Object[] keys, int n) throws Exception {
429 +        FileInputStream fr = null;
430 +        try {
431 +            fr = new FileInputStream(wordFile);
432 +        } catch (IOException ex) {
433 +            System.out.println("No word file. Using String.valueOf(i)");
434 +            for (int i = 0; i < n; i++)
435 +                keys[i] = String.valueOf(i);
436 +            return;
437 +        }
438 +
439 +        BufferedInputStream in = new BufferedInputStream(fr);
440 +        int k = 0;
441 +        outer:while (k < n) {
442 +            StringBuffer sb = new StringBuffer();
443 +            for (;;) {
444 +                int c = in.read();
445 +                if (c < 0)
446 +                    break outer;
447 +                char ch = (char)c;
448 +                if (ch == '\n') {
449 +                    keys[k++] = sb.toString();
450 +                    break;
451 +                }
452 +                if (!Character.isWhitespace(ch))
453 +                    sb.append(ch);
454 +            }
455 +        }
456 +        in.close();
457 +
458 +        // fill up remaining keys with path-like compounds of previous pairs
459 +        int j = 0;
460 +        while (k < n)
461 +            keys[k++] = (String)keys[j++] + "/" + (String)keys[j];
462 +    }
463  
464   }
465  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines