ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/StringMapLoops.java
Revision: 1.1
Committed: Sun Aug 7 19:25:55 2005 UTC (18 years, 9 months ago) by dl
Branch: MAIN
Log Message:
Add exchanger performance tests; update others

File Contents

# User Rev Content
1 dl 1.1 /*
2     * @test
3     * @synopsis Exercise multithreaded maps, by default
4     * ConcurrentHashMap. Each thread does a random walk though elements
5     * of "key" array. On each iteration, it checks if table includes key.
6     * If absent, with probablility pinsert it inserts it, and if present,
7     * with probablility premove it removes it. (pinsert and premove are
8     * expressed as percentages to simplify parsing from command line.)
9     */
10     /*
11     * Written by Doug Lea with assistance from members of JCP JSR-166
12     * Expert Group and released to the public domain. Use, modify, and
13     * redistribute this code in any way without acknowledgement.
14     */
15    
16    
17     import java.util.*;
18     import java.util.concurrent.*;
19    
20     public class StringMapLoops {
21     static int nkeys = 1000;
22     static int pinsert = 60;
23     static int premove = 2;
24     static int maxThreads = 100;
25     static int nops = 1000000;
26     static int removesPerMaxRandom;
27     static int insertsPerMaxRandom;
28    
29     static final ExecutorService pool = Executors.newCachedThreadPool();
30    
31     public static void main(String[] args) throws Exception {
32    
33     Class mapClass = null;
34     if (args.length > 0) {
35     try {
36     mapClass = Class.forName(args[0]);
37     } catch(ClassNotFoundException e) {
38     throw new RuntimeException("Class " + args[0] + " not found.");
39     }
40     }
41     else
42     mapClass = java.util.concurrent.ConcurrentHashMap.class;
43    
44     if (args.length > 1)
45     maxThreads = Integer.parseInt(args[1]);
46    
47     if (args.length > 2)
48     nkeys = Integer.parseInt(args[2]);
49    
50     if (args.length > 3)
51     pinsert = Integer.parseInt(args[3]);
52    
53     if (args.length > 4)
54     premove = Integer.parseInt(args[4]);
55    
56     if (args.length > 5)
57     nops = Integer.parseInt(args[5]);
58    
59     // normalize probabilities wrt random number generator
60     removesPerMaxRandom = (int)(((double)premove/100.0 * 0x7FFFFFFFL));
61     insertsPerMaxRandom = (int)(((double)pinsert/100.0 * 0x7FFFFFFFL));
62    
63     System.out.print("Class: " + mapClass.getName());
64     System.out.print(" threads: " + maxThreads);
65     System.out.print(" size: " + nkeys);
66     System.out.print(" ins: " + pinsert);
67     System.out.print(" rem: " + premove);
68     System.out.print(" ops: " + nops);
69     System.out.println();
70    
71     String[] key = makeKeys(nkeys);
72    
73     int k = 1;
74     int warmups = 2;
75     for (int i = 1; i <= maxThreads;) {
76     Thread.sleep(100);
77     test(i, nkeys, key, mapClass);
78     shuffleKeys(key);
79     if (warmups > 0)
80     --warmups;
81     else if (i == k) {
82     k = i << 1;
83     i = i + (i >>> 1);
84     }
85     else if (i == 1 && k == 2) {
86     i = k;
87     warmups = 1;
88     }
89     else
90     i = k;
91     }
92     pool.shutdown();
93     }
94    
95     static String[] makeKeys(int n) {
96     LoopHelpers.SimpleRandom rng = new LoopHelpers.SimpleRandom();
97     String[] key = new String[n];
98     for (int i = 0; i < key.length; ++i) {
99     int k = 0;
100     int len = 1 + (rng.next() & 0xf);
101     char[] c = new char[len * 4];
102     for (int j = 0; j < len; ++j) {
103     int r = rng.next();
104     c[k++] = (char)(' ' + (r & 0x7f));
105     r >>>= 8;
106     c[k++] = (char)(' ' + (r & 0x7f));
107     r >>>= 8;
108     c[k++] = (char)(' ' + (r & 0x7f));
109     r >>>= 8;
110     c[k++] = (char)(' ' + (r & 0x7f));
111     }
112     key[i] = new String(c);
113     }
114     return key;
115     }
116    
117     static void shuffleKeys(String[] key) {
118     Random rng = new Random();
119     for (int i = key.length; i > 1; --i) {
120     int j = rng.nextInt(i);
121     String tmp = key[j];
122     key[j] = key[i-1];
123     key[i-1] = tmp;
124     }
125     }
126    
127     static void test(int i, int nkeys, String[] key, Class mapClass) throws Exception {
128     System.out.print("Threads: " + i + "\t:");
129     Map<String, String> map = (Map<String,String>)mapClass.newInstance();
130     // Uncomment to start with a non-empty table
131     // for (int j = 0; j < nkeys; j += 4) // start 1/4 occupied
132     // map.put(key[j], key[j]);
133     LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
134     CyclicBarrier barrier = new CyclicBarrier(i+1, timer);
135     for (int t = 0; t < i; ++t)
136     pool.execute(new Runner(t, map, key, barrier));
137     barrier.await();
138     barrier.await();
139     long time = timer.getTime();
140     long tpo = time / (i * (long)nops);
141     System.out.print(LoopHelpers.rightJustify(tpo) + " ns per op");
142     double secs = (double)(time) / 1000000000.0;
143     System.out.println("\t " + secs + "s run time");
144     map.clear();
145     }
146    
147     static class Runner implements Runnable {
148     final Map<String,String> map;
149     final String[] key;
150     final LoopHelpers.SimpleRandom rng;
151     final CyclicBarrier barrier;
152     int position;
153     int total;
154    
155     Runner(int id, Map<String,String> map, String[] key, CyclicBarrier barrier) {
156     this.map = map;
157     this.key = key;
158     this.barrier = barrier;
159     position = key.length / 2;
160     rng = new LoopHelpers.SimpleRandom((id + 1) * 8862213513L);
161     rng.next();
162     }
163    
164     int step() {
165     // random-walk around key positions, bunching accesses
166     int r = rng.next();
167     position += (r & 7) - 3;
168     while (position >= key.length) position -= key.length;
169     while (position < 0) position += key.length;
170    
171     String k = key[position];
172     String x = map.get(k);
173    
174     if (x != null) {
175     if (r < removesPerMaxRandom) {
176     if (map.remove(k) != null) {
177     position = total % key.length; // move from position
178     return 2;
179     }
180     }
181     }
182     else if (r < insertsPerMaxRandom) {
183     ++position;
184     map.put(k, k);
185     return 2;
186     }
187    
188     total += r;
189     return 1;
190     }
191    
192     public void run() {
193     try {
194     barrier.await();
195     int ops = nops;
196     while (ops > 0)
197     ops -= step();
198     barrier.await();
199     }
200     catch (Exception ex) {
201     ex.printStackTrace();
202     }
203     }
204     }
205     }
206