From be7b637427f99f49844f489efcdcab68d5c55e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfonso=C2=B2=20Peterssen?= Date: Tue, 25 Aug 2020 11:28:27 +0200 Subject: [PATCH 1/3] Make unit tests resilient to the encoded graph cache being purged by idle compiler threads. --- .../truffle/test/EncodedGraphCacheTest.java | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java index 61c9d8930665..0dfcd1bf21f5 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java @@ -218,27 +218,39 @@ public void testCacheIsDisabled() { @Test public void testCacheIsEnabled() { - testHelper(100, 100_000, compiler -> { - assertTrue("InvalidationTestNode.execute is cached", - encodedGraphCacheContains(compiler, testMethod)); - }); + boolean[] cacheContainsTargetGraph = {false}; + for (int attempts = 0; attempts < 10 && !cacheContainsTargetGraph[0]; attempts++) { + testHelper(100, 100_000, compiler -> { + cacheContainsTargetGraph[0] = encodedGraphCacheContains(compiler, testMethod); + }); + } + Assert.assertTrue("InvalidationTestNode.execute is cached", cacheContainsTargetGraph[0]); } @Test public void testCacheCapacity() { - testHelper(1, 100_000, compiler -> { - EconomicMap cache = compiler.getPartialEvaluator().getOrCreateEncodedGraphCache(); - // A single compilation should cache more than 1 graph. - Assert.assertEquals("Cache can hold at most 1 element", 1, cache.size()); - }); + boolean[] cacheHolds1Element = {false}; + for (int attempts = 0; attempts < 10 && !cacheHolds1Element[0]; attempts++) { + testHelper(1, 100_000, compiler -> { + EconomicMap cache = compiler.getPartialEvaluator().getOrCreateEncodedGraphCache(); + // The cache can have at most 1 element, but it can be purged anytime. + Assert.assertTrue("Cache holds at most 1 element", cache.size() <= 1); + cacheHolds1Element[0] = (cache.size() == 1); // can be empty + }); + } + Assert.assertTrue("Cache holds exactly 1 element", cacheHolds1Element[0]); } @Test public void testUnboundedCacheCapacity() { - testHelper(-1, 100_000, compiler -> { - EconomicMap cache = compiler.getPartialEvaluator().getOrCreateEncodedGraphCache(); - Assert.assertFalse("Cache has some elements", cache.isEmpty()); - }); + boolean[] nonEmptyGraphCache = {false}; + for (int attempts = 0; attempts < 10 && !nonEmptyGraphCache[0]; attempts++) { + testHelper(-1, 100_000, compiler -> { + EconomicMap cache = compiler.getPartialEvaluator().getOrCreateEncodedGraphCache(); + nonEmptyGraphCache[0] = !cache.isEmpty(); + }); + } + Assert.assertTrue("Unbounded cache was populated", nonEmptyGraphCache[0]); } @Test From fdb00e8c41e1b4289c8811bc609d35175d31723b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfonso=C2=B2=20Peterssen?= Date: Tue, 25 Aug 2020 13:11:04 +0200 Subject: [PATCH 2/3] Make cache invalidation test more robust. --- .../truffle/test/EncodedGraphCacheTest.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java index 0dfcd1bf21f5..907300fd3efb 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java @@ -195,12 +195,15 @@ public void testCacheInvalidation() { encodedGraphCacheContains(truffleCompiler, testMethod)); // Retry again, the encoded graph is re-parsed without the (invalidated) assumption. - // Compilation succeeds. - callTarget = compileAST(rootTestNode); - - assertTrue("Re-parsed graph is in the cache", - encodedGraphCacheContains(truffleCompiler, testMethod)); + boolean[] graphWasCached = {false}; + for (int attempts = 0; attempts < 10 && !graphWasCached[0]; attempts++) { + // Compilation succeeds. + callTarget = compileAST(rootTestNode); + // But the cache can be purged anytime, retry if the graph is not cached. + graphWasCached[0] = encodedGraphCacheContains(truffleCompiler, testMethod); + } + Assert.assertTrue("Re-parsed graph was cached", graphWasCached[0]); Assert.assertEquals(42, (int) callTarget.call()); } From 612d2afc9432e127ea86604ccb0f2d783a1e6cbf Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 25 Aug 2020 16:56:31 +0200 Subject: [PATCH 3/3] do not use ThreadPoolExecutor.getTaskCount as it return an approximation --- .../src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java index 91a143db69a6..fa0691b85692 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java @@ -805,10 +805,12 @@ private void compile(String classPath, LibGraalParams libgraal) throws IOExcepti float selector = Math.max(0, startAtCompile); float selectorStep = maxCompiles < allCompiles ? (float) allCompiles / maxCompiles : 1.0f; int repeat = Options.Repeat.getValue(harnessOptions); + long taskCount = 0; for (Map.Entry e : toBeCompiled.entrySet()) { if (compilationNum >= startAtCompile && compilationNum < stopAtCompile) { if (Math.round(selector) == compilationNum) { for (int i = 0; i < repeat; i++) { + taskCount++; threadPool.submit(new Runnable() { @Override public void run() { @@ -825,7 +827,6 @@ public void run() { int wakeups = 0; long lastCompletedTaskCount = 0; int statsInterval = Options.StatsInterval.getValue(harnessOptions); - long taskCount = threadPool.getTaskCount(); long completedTaskCount; do { completedTaskCount = threadPool.getCompletedTaskCount();