ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/MapCheck.java
Revision: 1.15
Committed: Tue Jan 22 20:31:05 2013 UTC (11 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.14: +2 -2 lines
Log Message:
whitespace

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 */
6 /**
7 * @test
8 * @synopsis Times and checks basic map operations
9 *
10 * When run with "s" second arg, this requires file "testwords", which
11 * is best used with real words. We can't check in this file, but you
12 * can create one from a real dictionary (1 line per word) and then run
13 * linux "shuf" to randomize entries.
14 */
15 import java.util.*;
16 import java.io.*;
17
18 public class MapCheck {
19 static final Object MISSING = new Object();
20 static TestTimer timer = new TestTimer();
21 static Class eclass;
22 static Class mapClass = java.util.concurrent.ConcurrentHashMap.class;
23
24 static final LoopHelpers.SimpleRandom srng = new LoopHelpers.SimpleRandom();
25 static final Random rng = new Random(3152688);
26
27 static volatile int checkSum;
28
29 static void reallyAssert(boolean b) {
30 if (!b) throw new Error("Failed Assertion");
31 }
32
33 public static void main(String[] args) throws Exception {
34 int numTests = 100;
35 int size = 36864; // about midway of HashMap resize interval
36
37 if (args.length == 0)
38 System.out.println("Usage: MapCheck mapclass [int|float|string|object] [trials] [size] [serialtest]");
39
40 if (args.length > 0) {
41 try {
42 mapClass = Class.forName(args[0]);
43 } catch (ClassNotFoundException e) {
44 throw new RuntimeException("Class " + args[0] + " not found.");
45 }
46 }
47
48 if (args.length > 1) {
49 String et = args[1].toLowerCase();
50 if (et.startsWith("i"))
51 eclass = java.lang.Integer.class;
52 else if (et.startsWith("f"))
53 eclass = java.lang.Float.class;
54 else if (et.startsWith("s"))
55 eclass = java.lang.String.class;
56 else if (et.startsWith("d"))
57 eclass = java.lang.Double.class;
58 }
59 if (eclass == null)
60 eclass = Object.class;
61
62 if (args.length > 2)
63 numTests = Integer.parseInt(args[2]);
64
65 if (args.length > 3)
66 size = Integer.parseInt(args[3]);
67
68 boolean doSerializeTest = args.length > 4;
69
70 while ((size & 3) != 0) ++size;
71
72 System.out.print("Class: " + mapClass.getName());
73 System.out.print(" elements: " + eclass.getName());
74 System.out.print(" trials: " + numTests);
75 System.out.print(" size: " + size);
76 System.out.println();
77
78 Object[] key = new Object[size];
79 Object[] absent = new Object[size];
80 initializeKeys(key, absent, size);
81
82 precheck(size, key, absent);
83
84 for (int rep = 0; rep < numTests; ++rep) {
85 mainTest(newMap(), key, absent);
86 if ((rep & 3) == 3 && rep < numTests - 1) {
87 shuffle(key);
88 // Thread.sleep(10);
89 }
90 }
91
92 TestTimer.printStats();
93
94 checkNullKey();
95
96 if (doSerializeTest)
97 serTest(newMap(), size);
98 }
99
100 static Map newMap() {
101 try {
102 return (Map) mapClass.newInstance();
103 } catch (Exception e) {
104 throw new RuntimeException("Can't instantiate " + mapClass + ": " + e);
105 }
106 }
107
108 static void precheck(int n, Object[] key, Object[] abs) {
109 int ck = 0;
110 Map s = newMap();
111 for (int i = 0; i < n; i++) {
112 Object k = key[i];
113 if (k == null) throw new Error("Null key at" + i);
114 ck += System.identityHashCode(k);
115 Object v = s.put(k, k);
116 if (v != null)
117 throw new Error("Duplicate " + k + " / " + v);
118 }
119 for (int i = 0; i < n; i++) {
120 Object k = abs[i];
121 if (k == null) throw new Error("Null key at" + i);
122 ck += System.identityHashCode(k);
123 Object v = s.put(k, k);
124 if (v != null)
125 throw new Error("Duplicate " + k + " / " + v);
126 }
127 checkSum += ck;
128 }
129
130 static void checkNullKey() {
131 Map m = newMap();
132 Object x = new Object();
133 Object v;
134 try {
135 m.put(null, x);
136 v = m.get(null);
137 } catch (NullPointerException npe) {
138 System.out.println("Map does not allow null keys");
139 return;
140 }
141 if (v != x) throw new Error();
142 if (m.remove(null) != v) throw new Error();
143 if (m.get(null) != null) throw new Error();
144 }
145
146
147 static void getTest(String nm, int n, Map s, Object[] key, int expect) {
148 int sum = 0;
149 timer.start(nm, n);
150 for (int i = 0; i < n; i++) {
151 Object v = s.get(key[i]);
152 if (v != null && v.getClass() == eclass)
153 ++sum;
154 }
155 timer.finish();
156 reallyAssert(sum == expect);
157 checkSum += sum;
158 }
159
160
161 // unused
162 static void getTestBoxed(String nm, int n, Map s, Object[] key, int expect) {
163 int sum = 0;
164 Map<Integer,Integer> intMap = (Map<Integer,Integer>)s;
165 timer.start(nm, n);
166 for (int i = 0; i < n; i++) {
167 if (intMap.get(i) != i) ++sum;
168 }
169 timer.finish();
170 reallyAssert(sum == expect);
171 }
172
173 static void remTest(String nm, int n, Map s, Object[] key, int expect) {
174 int sum = 0;
175 timer.start(nm, n);
176 for (int i = 0; i < n; i++) {
177 if (s.remove(key[i]) != null) ++sum;
178 }
179 timer.finish();
180 reallyAssert(sum == expect);
181 checkSum += sum;
182 }
183
184 static void clrTest(int n, Map s) {
185 String nm = "Remove Present ";
186 timer.start(nm, n);
187 s.clear();
188 timer.finish();
189 reallyAssert(s.isEmpty());
190 }
191
192 static void putTest(String nm, int n, Map s, Object[] key, int expect) {
193 int sum = 0;
194 timer.start(nm, n);
195 for (int i = 0; i < n; i++) {
196 Object k = key[i];
197 Object v = s.put(k, k);
198 if (v == null) ++sum;
199 }
200 timer.finish();
201 reallyAssert(sum == expect);
202 checkSum += sum;
203 }
204
205 static void keyTest(String nm, int n, Map s, Object[] key, int expect) {
206 int sum = 0;
207 timer.start(nm, n);
208 for (int i = 0; i < n; i++) {
209 if (s.containsKey(key[i])) ++sum;
210 }
211 timer.finish();
212 reallyAssert(sum == expect);
213 checkSum += sum;
214 }
215
216 // version without timing for uncategorized tests
217 static void untimedKeyTest(String nm, int n, Map s, Object[] key, int expect) {
218 int sum = 0;
219 for (int i = 0; i < n; i++) {
220 if (s.containsKey(key[i])) ++sum;
221 }
222 reallyAssert(sum == expect);
223 checkSum += sum;
224 }
225
226 static void remHalfTest(String nm, int n, Map s, Object[] key, int expect) {
227 int sum = 0;
228 timer.start(nm, n/2);
229 for (int i = n-2; i >= 0; i-=2) {
230 if (s.remove(key[i]) != null) ++sum;
231 }
232 timer.finish();
233 reallyAssert(sum == expect);
234 checkSum += sum;
235 }
236
237 static void valTest(Map s, Object[] key) {
238 int size = s.size();
239 int sum = 0;
240 timer.start("Traverse key or value ", size);
241 if (s.containsValue(MISSING)) ++sum;
242 timer.finish();
243 reallyAssert(sum == 0);
244 checkSum += sum;
245 }
246
247
248 static Object kitTest(Map s, int size) {
249 Object last = null;
250 int sum = 0;
251 timer.start("Traverse key or value ", size);
252 for (Iterator it = s.keySet().iterator(); it.hasNext(); ) {
253 Object x = it.next();
254 if (x != last && x != null && x.getClass() == eclass)
255 ++sum;
256 last = x;
257 }
258 timer.finish();
259 reallyAssert(sum == size);
260 checkSum += sum;
261 return last;
262 }
263
264 static Object vitTest(Map s, int size) {
265 Object last = null;
266 int sum = 0;
267 timer.start("Traverse key or value ", size);
268 for (Iterator it = s.values().iterator(); it.hasNext(); ) {
269 Object x = it.next();
270 if (x != last && x != null && x.getClass() == eclass)
271 ++sum;
272 last = x;
273 }
274 timer.finish();
275 reallyAssert(sum == size);
276 checkSum += sum;
277 return last;
278 }
279
280 static void eitTest(Map s, int size) {
281 int sum = 0;
282 timer.start("Traverse entry ", size);
283 for (Iterator it = s.entrySet().iterator(); it.hasNext(); ) {
284 Map.Entry e = (Map.Entry)it.next();
285 Object k = e.getKey();
286 Object v = e.getValue();
287 if (k != null && k.getClass() == eclass &&
288 v != null && v.getClass() == eclass)
289 ++sum;
290 }
291 timer.finish();
292 reallyAssert(sum == size);
293 checkSum += sum;
294 }
295
296 static void itRemTest(Map s, int size) {
297 int sz = s.size();
298 reallyAssert(sz == size);
299 timer.start("Remove Present ", size);
300 int sum = 0;
301 for (Iterator it = s.keySet().iterator(); it.hasNext(); ) {
302 it.next();
303 it.remove();
304 ++sum;
305 }
306 timer.finish();
307 reallyAssert(sum == sz);
308 checkSum += sum;
309 }
310
311 static void itHalfRemTest(Map s, int size) {
312 int sz = s.size();
313 reallyAssert(sz == size);
314 timer.start("Remove Present ", size);
315 int sum = 0;
316 for (Iterator it = s.keySet().iterator(); it.hasNext(); ) {
317 it.next();
318 it.remove();
319 if (it.hasNext())
320 it.next();
321 ++sum;
322 }
323 timer.finish();
324 reallyAssert(sum == sz / 2);
325 checkSum += sum;
326 }
327
328 static void putAllTest(String nm, int n, Map src, Map dst) {
329 timer.start(nm, n);
330 dst.putAll(src);
331 timer.finish();
332 reallyAssert(src.size() == dst.size());
333 }
334
335 static void serTest(Map s, int size) throws Exception {
336 if (!(s instanceof Serializable))
337 return;
338 System.out.print("Serialize : ");
339
340 for (int i = 0; i < size; i++) {
341 s.put(new Integer(i), Boolean.TRUE);
342 }
343
344 long startTime = System.currentTimeMillis();
345
346 FileOutputStream fs = new FileOutputStream("MapCheck.dat");
347 ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(fs));
348 out.writeObject(s);
349 out.close();
350
351 FileInputStream is = new FileInputStream("MapCheck.dat");
352 ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(is));
353 Map m = (Map) in.readObject();
354
355 long endTime = System.currentTimeMillis();
356 long time = endTime - startTime;
357
358 System.out.print(time + "ms");
359
360 if (s instanceof IdentityHashMap) return;
361 reallyAssert(s.equals(m));
362 }
363
364 static void mainTest(Map s, Object[] key, Object[] absent) {
365 int size = key.length;
366
367 putTest("Add Absent ", size, s, key, size);
368 reallyAssert(s.size() == size);
369 getTest("Access Present ", size, s, key, size);
370 getTest("Search Absent ", size, s, absent, 0);
371 kitTest(s, size);
372 vitTest(s, size);
373 eitTest(s, size);
374 putTest("Modify Present ", size, s, key, 0);
375 reallyAssert(s.size() == size);
376 untimedKeyTest("Access Present ", size, s, key, size);
377 keyTest("Search Absent ", size, s, absent, 0);
378 valTest(s, key);
379 remTest("Search Absent ", size, s, absent, 0);
380 reallyAssert(s.size() == size);
381 remHalfTest("Remove Present ", size, s, key, size / 2);
382 reallyAssert(s.size() == size / 2);
383 getTest("Access Present ", size, s, key, size / 2);
384 putTest("Add Absent ", size, s, key, size / 2);
385 reallyAssert(s.size() == size);
386 getTest("Access Present ", size, s, key, size);
387 getTest("Search Absent ", size, s, absent, 0);
388 itRemTest(s, size);
389 putTest("Add Absent ", size, s, key, size);
390 reallyAssert(s.size() == size);
391 getTest("Access Present ", size, s, key, size);
392 untimedKeyTest("Access Present ", size, s, key, size);
393 kitTest(s, size);
394 vitTest(s, size);
395 eitTest(s, size);
396 twoMapTest1(s, key, absent);
397 twoMapTest2(s, key, absent);
398 }
399
400 static void twoMapTest1(Map s, Object[] key, Object[] absent) {
401 int size = s.size();
402 Map s2 = newMap();
403 putAllTest("Add Absent ", size, s, s2);
404 getTest("Access Present ", size, s2, key, size);
405 itHalfRemTest(s2, size);
406 reallyAssert(s2.size() == size / 2);
407 itHalfRemTest(s2, size / 2);
408 reallyAssert(s2.size() == size / 4);
409 putTest("Add Absent ", size, s2, absent, size);
410 putTest("Add Absent ", size, s2, key, size * 3 / 4);
411 reallyAssert(s2.size() == size * 2);
412 clrTest(size, s2);
413 }
414
415 static void twoMapTest2(Map s, Object[] key, Object[] absent) {
416 int size = key.length;
417
418 Map s2 = newMap();
419 putAllTest("Add Absent ", size, s, s2);
420 putAllTest("Modify Present ", size, s, s2);
421
422 Object lastkey = kitTest(s2, size);
423 Object hold = s2.get(lastkey);
424 int sum = 0;
425
426 timer.start("Traverse entry ", size * 12); // 12 until finish
427
428 int sh1 = s.hashCode() - s2.hashCode();
429 reallyAssert(sh1 == 0);
430
431 boolean eq1 = s2.equals(s);
432 boolean eq2 = s.equals(s2);
433 reallyAssert(eq1 && eq2);
434
435 Set es2 = s2.entrySet();
436 for (Iterator it = s.entrySet().iterator(); it.hasNext(); ) {
437 Object entry = it.next();
438 if (es2.contains(entry)) ++sum;
439 }
440 reallyAssert(sum == size);
441
442 s2.put(lastkey, MISSING);
443
444 int sh2 = s.hashCode() - s2.hashCode();
445 reallyAssert(sh2 != 0);
446
447 eq1 = s2.equals(s);
448 eq2 = s.equals(s2);
449 reallyAssert(!eq1 && !eq2);
450
451 sum = 0;
452 for (Iterator it = s.entrySet().iterator(); it.hasNext(); ) {
453 Map.Entry e = (Map.Entry)it.next();
454 e.setValue(absent[sum++]);
455 }
456 reallyAssert(sum == size);
457 for (Iterator it = s2.entrySet().iterator(); it.hasNext(); ) {
458 Map.Entry e = (Map.Entry)it.next();
459 e.setValue(s.get(e.getKey()));
460 }
461
462 timer.finish();
463
464 int rmiss = 0;
465 timer.start("Remove Present ", size * 2);
466 Iterator s2i = s2.entrySet().iterator();
467 Set es = s.entrySet();
468 while (s2i.hasNext()) {
469 if (!es.remove(s2i.next()))
470 ++rmiss;
471 }
472 timer.finish();
473 reallyAssert(rmiss == 0);
474
475 clrTest(size, s2);
476 reallyAssert(s2.isEmpty() && s.isEmpty());
477 }
478
479 static void itTest4(Map s, int size, int pos) {
480 IdentityHashMap seen = new IdentityHashMap(size);
481 reallyAssert(s.size() == size);
482 int sum = 0;
483 timer.start("Iter XEntry ", size);
484 Iterator it = s.entrySet().iterator();
485 Object k = null;
486 Object v = null;
487 for (int i = 0; i < size-pos; ++i) {
488 Map.Entry x = (Map.Entry)(it.next());
489 k = x.getKey();
490 v = x.getValue();
491 seen.put(k, k);
492 if (x != MISSING)
493 ++sum;
494 }
495 reallyAssert(s.containsKey(k));
496 it.remove();
497 reallyAssert(!s.containsKey(k));
498 while (it.hasNext()) {
499 Map.Entry x = (Map.Entry)(it.next());
500 Object k2 = x.getKey();
501 seen.put(k2, k2);
502 if (x != MISSING)
503 ++sum;
504 }
505
506 reallyAssert(s.size() == size-1);
507 s.put(k, v);
508 reallyAssert(seen.size() == size);
509 timer.finish();
510 reallyAssert(sum == size);
511 reallyAssert(s.size() == size);
512 }
513
514
515
516 static void initializeKeys(Object[] key, Object[] absent, int size) {
517 if (eclass == Object.class) {
518 for (int i = 0; i < size; ++i) key[i] = new Object();
519 for (int i = 0; i < size; ++i) absent[i] = new Object();
520 }
521 else if (eclass == Integer.class) {
522 initInts(key, absent, size);
523 }
524 else if (eclass == Float.class) {
525 initFloats(key, absent, size);
526 }
527 else if (eclass == Double.class) {
528 initDoubles(key, absent, size);
529 }
530 else if (eclass == String.class) {
531 initWords(size, key, absent);
532 }
533 else
534 throw new Error("unknown type");
535 }
536
537 static void initInts(Object[] key, Object[] absent, int size) {
538 for (int i = 0; i < size; ++i)
539 key[i] = Integer.valueOf(i);
540 Map m = newMap();
541 int k = 0;
542 while (k < size) {
543 int r = srng.next();
544 if (r < 0 || r >= size) {
545 Integer ir = Integer.valueOf(r);
546 if (m.put(ir, ir) == null)
547 absent[k++] = ir;
548 }
549 }
550 }
551
552 static void initFloats(Object[] key, Object[] absent, int size) {
553 Map m = newMap();
554 for (int i = 0; i < size; ++i) {
555 float r = Float.valueOf(i);
556 key[i] = r;
557 m.put(r, r);
558 }
559 int k = 0;
560 while (k < size) {
561 float r = rng.nextFloat();
562 Float ir = Float.valueOf(r);
563 if (m.put(ir, ir) == null)
564 absent[k++] = ir;
565 }
566 }
567
568 static void initDoubles(Object[] key, Object[] absent, int size) {
569 Map m = newMap();
570 for (int i = 0; i < size; ++i) {
571 double r = Double.valueOf(i);
572 key[i] = r;
573 m.put(r, r);
574 }
575 int k = 0;
576 while (k < size) {
577 double r = rng.nextDouble();
578 Double ir = Double.valueOf(r);
579 if (m.put(ir, ir) == null)
580 absent[k++] = ir;
581 }
582 }
583
584 // Use as many real words as possible, then use fake random words
585
586 static void initWords(int size, Object[] key, Object[] abs) {
587 String fileName = "testwords.txt";
588 int ki = 0;
589 int ai = 0;
590 try {
591 FileInputStream fr = new FileInputStream(fileName);
592 BufferedInputStream in = new BufferedInputStream(fr);
593 while (ki < size || ai < size) {
594 StringBuffer sb = new StringBuffer();
595 for (;;) {
596 int c = in.read();
597 if (c < 0) {
598 if (ki < size)
599 randomWords(key, ki, size);
600 if (ai < size)
601 randomWords(abs, ai, size);
602 in.close();
603 return;
604 }
605 if (c == '\n') {
606 String s = sb.toString();
607 if (ki < size)
608 key[ki++] = s;
609 else
610 abs[ai++] = s;
611 break;
612 }
613 sb.append((char) c);
614 }
615 }
616 in.close();
617 }
618 catch (IOException ex) {
619 System.out.println("Can't read words file:" + ex);
620 throw new Error(ex);
621 }
622 }
623
624
625 static void randomWords(Object[] ws, int origin, int size) {
626 for (int i = origin; i < size; ++i) {
627 int k = 0;
628 int len = 2 + (srng.next() & 0xf);
629 char[] c = new char[len * 4 + 1];
630 for (int j = 1; j < len; ++j) {
631 int r = srng.next();
632 c[k++] = (char) (' ' + (r & 0x7f));
633 r >>>= 8;
634 c[k++] = (char) (' ' + (r & 0x7f));
635 r >>>= 8;
636 c[k++] = (char) (' ' + (r & 0x7f));
637 r >>>= 8;
638 c[k++] = (char) (' ' + (r & 0x7f));
639 }
640 c[k++] = (char) ((i & 31) | 1); // never == to any testword
641 ws[i] = new String(c);
642 }
643 }
644
645 static final class TestTimer {
646 private String name;
647 private long numOps;
648 private long startTime;
649
650 static final java.util.TreeMap accum = new java.util.TreeMap();
651
652 static void printStats() {
653 for (Iterator it = accum.entrySet().iterator(); it.hasNext(); ) {
654 Map.Entry e = (Map.Entry) it.next();
655 Stats stats = (Stats) e.getValue();
656 System.out.print(e.getKey() + ": ");
657 long s;
658 long n = stats.number;
659 if (n == 0) {
660 n = stats.firstn;
661 s = stats.first;
662 }
663 else
664 s = stats.sum;
665
666 double t = ((double) s) / n;
667 long nano = Math.round(t);
668 System.out.printf("%6d", + nano);
669 System.out.println();
670 }
671 }
672
673 void start(String name, long numOps) {
674 this.name = name;
675 this.numOps = numOps;
676 startTime = System.nanoTime();
677 }
678
679 void finish() {
680 long elapsed = System.nanoTime() - startTime;
681 Object st = accum.get(name);
682 if (st == null)
683 accum.put(name, new Stats(elapsed, numOps));
684 else
685 ((Stats) st).addTime(elapsed, numOps);
686 }
687
688 }
689
690 static final class Stats {
691 long sum;
692 long number;
693 long first;
694 long firstn;
695 Stats(long t, long n) {
696 first = t;
697 firstn = n;
698 }
699 void addTime(long t, long n) {
700 sum += t;
701 number += n;
702 }
703 }
704
705
706 static void shuffle(Object[] keys) {
707 int size = keys.length;
708 for (int i = size; i > 1; i--) {
709 int r = rng.nextInt(i);
710 Object t = keys[i-1];
711 keys[i-1] = keys[r];
712 keys[r] = t;
713 }
714 }
715
716 static void shuffle(ArrayList keys) {
717 int size = keys.size();
718 for (int i = size; i > 1; i--) {
719 int r = rng.nextInt(i);
720 Object t = keys.get(i-1);
721 keys.set(i-1, keys.get(r));
722 keys.set(r, t);
723 }
724 }
725
726 }