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

# Content
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