From 7da96fac6b2afc3fde51d768c442793e7337ff49 Mon Sep 17 00:00:00 2001 From: araq Date: Tue, 23 Jun 2026 20:59:28 +0200 Subject: [PATCH] nimsuggest tester: share one NIF cache across tests to cut suite time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even after only forcing a cold cache for the order-sensitive tests, every test still recompiled `system` from source into its own per-project cache — ~5s of cold start each, ~6 min for the suite, still too slow for CI. Point all tests at a single shared --nimcache so the standard library is compiled cold exactly once and every later test reuses those NIFs warm. The suite drops from ~6:15 to ~2:30 wall clock. Four tests break against warm NIFs and keep their own freshly-wiped cache: tsug_typedecl, ttype_decl and tdot4 rank results by per-symbol usage counts (not serialized into NIF, so warm vs cold orderings differ), and top_highlight SIGSEGVs when highlighting a warm-loaded module — a latent bug in the IC warm path that real (restarted) editor sessions can hit and that's worth fixing properly. Co-Authored-By: Claude Opus 4.8 --- nimsuggest/tester.nim | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/nimsuggest/tester.nim b/nimsuggest/tester.nim index 5c38ac90be..bd4ee5d4de 100644 --- a/nimsuggest/tester.nim +++ b/nimsuggest/tester.nim @@ -22,6 +22,13 @@ const import std/compilesettings +# All tests except the order-sensitive ones below share a single NIF cache. With a +# per-test cache (the default) every test recompiles `system` from source — ~5s of +# cold start each, which dominated the suite's wall-clock and blew CI's job timeout. +# Sharing one cache means `system` (and the rest of the standard library) is compiled +# cold exactly once; every later test reuses those NIFs warm. +let sharedNimcache = getTempDir() / "nimsuggest_shared_cache" + proc parseTest(filename: string; epcMode=false): Test = const cursorMarker = "#[!]#" let nimsug = "bin" / addFileExt("nimsuggest_testing", ExeExt) @@ -74,22 +81,26 @@ proc parseTest(filename: string; epcMode=false): Test = # else: ignore empty lines for better readability of the specs inc i tmp.close() - # A few `sug` tests rank results by per-symbol usage counts. Under IC those counts - # are not serialized into the NIF files, so a cold start (which re-walks `system` - # and saturates the counts of common types) and a warm start (which loads `system` - # from NIF without re-walking it) order the results differently — e.g. `string` - # outranks `int`, or `seq` drops below `Slice`. The tester runs each test's stdio - # variant cold and its EPC variant warm against the shared on-disk NIFs, so for - # these order-sensitive tests the two disagree. Give only those a private, freshly - # wiped cache so both variants start cold and deterministic. Every other test keeps - # reusing the warm cache, which roughly halves the suite's wall-clock time (and - # keeps it under CI's job timeout). - const coldCacheTests = ["tsug_typedecl.nim", "ttype_decl.nim"] + # A few tests need a cold, fully-walked `system` and break against warm NIFs: + # * tsug_typedecl, ttype_decl, tdot4 rank results by per-symbol usage counts, + # which are NOT serialized into the NIF files. A cold start re-walks `system` + # and saturates the counts of common types; a warm start loads `system` from + # NIF without re-walking it, so the order changes — e.g. `string` outranks + # `int`, `seq` drops below `Slice`, or `system.add` displaces `mstrutils.replace`. + # * top_highlight currently SIGSEGVs when highlighting a warm-loaded module + # (a latent bug in the IC warm path — real editor sessions restart nimsuggest + # and hit warm NIFs, so this is worth fixing properly). + # Give these a private, freshly wiped cache per variant. Every other test shares + # `sharedNimcache` and runs warm (and fast). + const coldCacheTests = ["tsug_typedecl.nim", "ttype_decl.nim", + "tdot4.nim", "top_highlight.nim"] if extractFilename(filename) in coldCacheTests: let nimcache = getTempDir() / ("nimsuggest_cache_" & extractFilename(result.dest).changeFileExt("") & (if epcMode: "_epc" else: "_stdin")) removeDir(nimcache) result.cmd.add " --nimcache:" & nimcache + else: + result.cmd.add " --nimcache:" & sharedNimcache # now that we know the markers, substitute them: for a in mitems(result.script): a[0] = a[0] % markers @@ -386,6 +397,9 @@ proc runTest(filename: string): int = proc main() = var failures = 0 + # Start every suite run from a clean shared cache so results don't depend on NIFs + # left over from a previous run (or an older compiler build). + removeDir(sharedNimcache) if os.paramCount() > 0: let x = os.paramStr(1) let xx = expandFilename x