protected void assertNoMemoryLeak(long memUsedPreviously, int iterations) { System.gc(); System.gc(); long memUsedAfter = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long memChange = memUsedAfter - memUsedPreviously; Assert.assertTrue(memChange < numIterations()*ACCEPTABLE_LEAK_PER_ITERATION + MEMORY_MARGIN_OF_ERROR, "Leaked too much memory: "+Strings.makeJavaSizeString(memChange)); // TODO Want a stronger assertion than this - it just says we don't have more apps than we created! int numApps = Iterables.size(weakApps.keySet()); assertTrue(numApps <= iterations, "numApps="+numApps+"; iterations="+iterations); int numLocs = Iterables.size(weakLocs.keySet()); assertTrue(numLocs <= iterations, "numLocs="+numLocs+"; iterations="+iterations); }
@Test(groups={"Integration", "Broken", "Manual"}) public void testRebindCheckingMemoryLeak() throws Exception { TestEntity c1 = origApp.addChild(EntitySpec.create(TestEntity.class)); c1.config().set(TestEntity.CONF_NAME, Strings.makeRandomId(1000000)); gcAndLog("before"); long used0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); for (int i=0; i<200; i++) { doPartialRebindOfIds(c1.getId()); origManagementContext.getGarbageCollector().gcIteration(); gcAndLog("iteration "+i); if (i==5) used0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); } gcAndLog("after"); long used1 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); Assert.assertTrue(used1 - used0 < 5000000, "Expected leak of less than 5M; leak was: from "+Strings.makeJavaSizeString(used0)+" to "+Strings.makeJavaSizeString(used1)); }
Time.sleep(Duration.millis(200)); // give things time to settle; means this number should be larger than others, if anything usedOriginally = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); log.info("Usage after first rebind: "+BrooklynGarbageCollector.makeBasicUsageString()+" ("+Strings.makeJavaSizeString(usedOriginally)+")"); } else { long usedNow = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); log.info("Usage: "+BrooklynGarbageCollector.makeBasicUsageString()+" ("+Strings.makeJavaSizeString(usedNow)+")"); Assert.assertFalse(usedNow-usedOriginally > MAX_ALLOWED_LEAK, "Leaked too much memory: "+Strings.makeJavaSizeString(usedNow)+" now used, was "+Strings.makeJavaSizeString(usedOriginally));