/** * Time a multi-threaded access to a cache. * * @return the timing stopwatch */ private <V> StopWatch timeMultiThreaded( String id, final Map<Integer, V> map, ValueFactory<V> factory) throws InterruptedException { StopWatch stopWatch = new StopWatch(id); for (int i = 0; i < 500; i++) { map.put(i, factory.newValue(i)); } Thread[] threads = new Thread[30]; stopWatch.start("Running threads"); for (int threadIndex = 0; threadIndex < threads.length; threadIndex++) { threads[threadIndex] = new Thread("Cache access thread " + threadIndex) { @Override public void run() { for (int j = 0; j < 1000; j++) { for (int i = 0; i < 1000; i++) { map.get(i); } } } }; } for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { if (thread.isAlive()) { thread.join(2000); } } stopWatch.stop(); return stopWatch; }
@Test @Ignore("Intended for use during development only") public void shouldBeFasterThanSynchronizedMap() throws Exception { Map<Integer, WeakReference<String>> synchronizedMap = Collections.synchronizedMap(new WeakHashMap<Integer, WeakReference<String>>()); StopWatch mapTime = timeMultiThreaded( "SynchronizedMap", synchronizedMap, new ValueFactory<WeakReference<String>>() { @Override public WeakReference<String> newValue(int v) { return new WeakReference<String>(String.valueOf(v)); } }); System.out.println(mapTime.prettyPrint()); this.map.setDisableTestHooks(true); StopWatch cacheTime = timeMultiThreaded( "WeakConcurrentCache", this.map, new ValueFactory<String>() { @Override public String newValue(int v) { return String.valueOf(v); } }); System.out.println(cacheTime.prettyPrint()); // We should be at least 4 time faster assertThat(cacheTime.getTotalTimeSeconds(), is(lessThan(mapTime.getTotalTimeSeconds() / 4.0))); }