@Test public void testLatency() throws Exception { final int THREADS = Runtime.getRuntime().availableProcessors(); final AtomicBoolean stopped = new AtomicBoolean(false); final long[] maxima = new long[THREADS]; final long[] maximaTimestamps = new long[THREADS]; final int[] loops = new int[THREADS]; Thread[] threads = new Thread[THREADS]; for(int i =0; i < THREADS; i++) { final int index = i; threads[index] = new Thread() { @Override public void run() { long max = -1; long maxTimestamp = -1; int runs; for (runs = 0; !stopped.get() && runs < (TOTAL_RUNS / THREADS); runs++) { long start = System.nanoTime(); Timestamper.next(); long duration = System.nanoTime() - start; if (duration > max) { max = duration; maxTimestamp = System.currentTimeMillis(); } Thread.yield(); } stopped.set(true); maxima[index] = max; maximaTimestamps[index] = maxTimestamp; loops[index] = runs; } }; } final long timestampOrigin = System.currentTimeMillis(); for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { thread.join(); } for (int i = 0; i < THREADS; i++) { System.out.println(threads[i] + " " + loops[i] + " runs, maximum latency " + TimeUnit.NANOSECONDS.toMillis(maxima[i]) + "ms [@ " + (maximaTimestamps[i] - timestampOrigin) + "ms]"); } for (int i = 0; i < THREADS; i++) { Assert.assertThat(maxima[i], lessThan(TimeUnit.MILLISECONDS.toNanos(200))); } }
public static long next() { int runs = 0; while (true) { long base = SlewClock.timeMillis() << BIN_DIGITS; long maxValue = base + ONE_MS - 1; for (long current = VALUE.get(), update = Math.max(base, current + 1); update < maxValue; current = VALUE.get(), update = Math.max(base, current + 1)) { if (VALUE.compareAndSet(current, update)) { if (runs > 1) { log(base, "Thread spin-waits on time to pass. Looped " + "{} times, you might want to increase -Dnet.sf.ehcache.util.Timestamper.shift", runs); } return update; } } ++runs; } }
Timestamper { public static long next() { int runs = 0; while (true) { long base = SlewClock.timeMillis() << BIN_DIGITS; long maxValue = base + ONE_MS - 1; for (long current = VALUE.get(), update = Math.max(base, current + 1); update < maxValue; current = VALUE.get(), update = Math.max(base, current + 1)) { if (VALUE.compareAndSet(current, update)) { if (runs > 1) { log(base, "Thread spin-waits on time to pass. Looped " + "{} times, you might want to increase -Dnet.sf.ehcache.util.Timestamper.shift", runs); } return update; } } ++runs; } } }
Timestamper { public static long next() { int runs = 0; while (true) { long base = SlewClock.timeMillis() << BIN_DIGITS; long maxValue = base + ONE_MS - 1; for (long current = VALUE.get(), update = Math.max(base, current + 1); update < maxValue; current = VALUE.get(), update = Math.max(base, current + 1)) { if (VALUE.compareAndSet(current, update)) { if (runs > 1) { log(base, "Thread spin-waits on time to pass. Looped " + "{} times, you might want to increase -Dnet.sf.ehcache.util.Timestamper.shift", runs); } return update; } } ++runs; } } private  Timestamper(); }
Timestamper { public static long next() { int runs = 0; while (true) { long base = SlewClock.timeMillis() << BIN_DIGITS; long maxValue = base + ONE_MS - 1; for (long current = VALUE.get(), update = Math.max(base, current + 1); update < maxValue; current = VALUE.get(), update = Math.max(base, current + 1)) { if (VALUE.compareAndSet(current, update)) { if (runs > 1) { log(base, "Thread spin-waits on time to pass. Looped " + "{} times, you might want to increase -Dnet.sf.ehcache.util.Timestamper.shift", runs); } return update; } } ++runs; } } private  Timestamper(); static long next(); }
Timestamper { public static long next() { int runs = 0; while (true) { long base = SlewClock.timeMillis() << BIN_DIGITS; long maxValue = base + ONE_MS - 1; for (long current = VALUE.get(), update = Math.max(base, current + 1); update < maxValue; current = VALUE.get(), update = Math.max(base, current + 1)) { if (VALUE.compareAndSet(current, update)) { if (runs > 1) { log(base, "Thread spin-waits on time to pass. Looped " + "{} times, you might want to increase -Dnet.sf.ehcache.util.Timestamper.shift", runs); } return update; } } ++runs; } } private  Timestamper(); static long next(); static final int BIN_DIGITS; static final int ONE_MS; }