@Override public boolean contains(Object o) { if (!(o instanceof Entry)) return false; Entry<?, ?> e = (Entry<?, ?>) o; Element v = SelectableConcurrentHashMap.this.get(e.getKey()); return v != null && v.equals(e.getValue()); }
/** * Check we get reasonable results for 2000 entries where entry 0 is accessed once increasing to * entry 1999 accessed 2000 times. * * <p>1 to 5000 population, with hit counts ranging from 1 to 500, not selecting lowest half. 5000 * tests S Cost No 7 38 99.24% confidence 8 27 99.46% confidence 9 10 10 11300 4 99.92% confidence * 12 2 20 11428 0 99.99% confidence * * <p>1 to 5000 population, with hit counts ranging from 1 to 500, not selecting lowest quarter. * 5000 tests S No 10 291 94.18% confidence 20 15 30 11536 1 99.99% confidence * * <p>For those with a statistical background the branch of stats which deals with this is * hypothesis testing and the Student's T distribution. The higher your sample the greater * confidence you can have in a hypothesis, in this case whether or not the "lowest" value lies in * the bottom half or quarter of the distribution. Adding samples rapidly increases confidence but * the return from extra sampling rapidly diminishes. * * <p>Cost is not affected much by sample size. Profiling shows that it is the iteration that is * causing most of the time. If we had access to the array backing Map, all would work very fast. * Still, it is fast enough. * * <p>A 99.99% confidence interval can be achieved that the "lowest" element is actually in the * bottom quarter of the hit count distribution. * * @throws IOException */ public void testLowest() throws IOException { createMemoryStore(MemoryStoreEvictionPolicy.LFU, 5000); Element element = null; Element newElement = null; for (int i = 0; i < 10; i++) { newElement = new Element("" + i, new Date()); store.put(newElement); int j; for (j = 0; j <= i; j++) { store.get("" + i); } if (i > 0) { element = ((LfuMemoryStore) store).findRelativelyUnused(newElement); assertTrue(!element.equals(newElement)); assertTrue(element.getHitCount() < 2); } } int lowestQuarterNotIdentified = 0; long findTime = 0; StopWatch stopWatch = new StopWatch(); for (int i = 10; i < 5000; i++) { store.put(new Element("" + i, new Date())); int j; int maximumHitCount = 0; for (j = 0; j <= i; j += 10) { store.get("" + i); maximumHitCount++; } stopWatch.getElapsedTime(); element = ((LfuMemoryStore) store).findRelativelyUnused(newElement); findTime += stopWatch.getElapsedTime(); long lowest = element.getHitCount(); long bottomQuarter = (Math.round(maximumHitCount / 4.0) + 1); assertTrue(!element.equals(newElement)); if (lowest > bottomQuarter) { lowestQuarterNotIdentified++; // LOG.info(i + " " + maximumHitCount + " " + element); } } LOG.info("Find time: " + findTime); assertTrue(findTime < 1500); LOG.info("Selections not in lowest quartile: " + lowestQuarterNotIdentified); assertTrue(lowestQuarterNotIdentified < 5); }
/** * Check we get reasonable results for 2000 entries where entry 0 is accessed once increasing to * entry 1999 accessed 2000 times. * * <p>1 to 5000 population, with hit counts ranging from 1 to 500, not selecting lowest half. 5000 * tests * * <p>Samples Cost No 7 38 99.24% confidence 8 27 99.46% confidence 9 10 10 11300 4 99.92% * confidence 12 2 20 11428 0 99.99% confidence * * <p>1 to 5000 population, with hit counts ranging from 1 to 500, not selecting lowest quarter. * 5000 tests S No 10 291 94.18% confidence 20 15 30 11536 1 99.99% confidence * * <p>For those with a statistical background the branch of stats which deals with this is * hypothesis testing and the Student's T distribution. The higher your sample the greater * confidence you can have in a hypothesis, in this case whether or not the "lowest" value lies in * the bottom half or quarter of the distribution. Adding samples rapidly increases confidence but * the return from extra sampling rapidly diminishes. * * <p>Cost is not affected much by sample size. Profiling shows that it is the iteration that is * causing most of the time. If we had access to the array backing Map, all would work very fast. * Still, it is fast enough. * * <p>A 99.99% confidence interval can be achieved that the "lowest" element is actually in the * bottom quarter of the hit count distribution. * * @throws java.io.IOException Performance: With a sample size of 10: 523ms for 5000 runs = 104 ?s * per run With a sample size of 30: 628ms for 5000 runs = 125 ?s per run */ @Test public void testLowest() throws IOException { createMemoryOnlyStore(MemoryStoreEvictionPolicy.LFU, 5000); // fully populate the otherwise we just find nulls for (int i = 0; i < 5000; i++) { Element newElement = new Element("" + i, new Date()); store.put(newElement); } Element element = null; Element newElement = null; for (int i = 0; i < 10; i++) { newElement = new Element("" + i, new Date()); store.put(newElement); int j; for (j = 0; j <= i; j++) { store.get("" + i); } if (i > 0) { try { element = (Element) GET_EVICTION_TARGET.invoke( PRIMARY_FACTORY.get(store), new Object(), Integer.MAX_VALUE); } catch (Exception e) { throw new RuntimeException(e); } assertTrue(!element.equals(newElement)); assertTrue(element.getHitCount() < 2); } } int lowestQuarterNotIdentified = 0; long findTime = 0; StopWatch stopWatch = new StopWatch(); for (int i = 10; i < 5000; i++) { store.put(new Element("" + i, new Date())); int j; int maximumHitCount = 0; for (j = 0; j <= i; j += 10) { store.get("" + i); maximumHitCount++; } stopWatch.getElapsedTime(); try { element = (Element) GET_EVICTION_TARGET.invoke( PRIMARY_FACTORY.get(store), new Object(), Integer.MAX_VALUE); } catch (Exception e) { throw new RuntimeException(e); } findTime += stopWatch.getElapsedTime(); long lowest = element.getHitCount(); long bottomQuarter = (Math.round(maximumHitCount / 4.0) + 1); assertTrue(!element.equals(newElement)); if (lowest > bottomQuarter) { LOG.info( "" + element.getKey() + " hit count: " + element.getHitCount() + " bottomQuarter: " + bottomQuarter); lowestQuarterNotIdentified++; } } LOG.info("Find time: " + findTime); assertTrue(findTime < 200); LOG.info("Selections not in lowest quartile: " + lowestQuarterNotIdentified); assertTrue(lowestQuarterNotIdentified <= 10); }