[libcxx-commits] [PATCH] D117361: [libc++] Persistently cache memoized operations during Lit configuration

Louis Dionne via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 14 14:20:58 PST 2022


ldionne created this revision.
Herald added a subscriber: arichardson.
ldionne requested review of this revision.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.

When invoking Lit repeatedly, we perform all the configuration checks
over and over again, which takes a lot of time. This patch allows caching
the result of configuration checks persistently across Lit invocations to
speed this up.

In theory, this should still be functionally correct since the cache
key should contain everything that determines the output of the
configuration check. However, in cases where e.g. the compiler has
changed but is at the same path as previously, the Lit configuration
checks will be cached even though technically the cache should have
been invalidated.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D117361

Files:
  libcxx/utils/libcxx/test/dsl.py


Index: libcxx/utils/libcxx/test/dsl.py
===================================================================
--- libcxx/utils/libcxx/test/dsl.py
+++ libcxx/utils/libcxx/test/dsl.py
@@ -37,13 +37,34 @@
   We pickle the cache key to make sure we store an immutable representation
   of it. If we stored an object and the object was referenced elsewhere, it
   could be changed from under our feet, which would break the cache.
+
+  We also store the cache for a given function persistently across invocations
+  of Lit. This dramatically speeds up the configuration of the test suite when
+  invoking Lit repeatedly, which is important for developer workflow. However,
+  with the current implementation that does not synchronize updates to the
+  persistent cache, this also means that one should not call a memoized
+  operation from multiple threads. This should normally not be a problem
+  since Lit configuration is single-threaded.
   """
   def decorator(function):
-    cache = {}
-    def f(*args, **kwargs):
-      cacheKey = pickle.dumps(extractCacheKey(*args, **kwargs))
+    def f(config, *args, **kwargs):
+      cacheRoot = os.path.join(config.test_exec_root, '__config_cache__')
+      persistentCache = os.path.join(cacheRoot, function.__name__)
+      if not os.path.exists(cacheRoot):
+        os.makedirs(cacheRoot)
+
+      cache = {}
+      # Load a cache from a previous Lit invocation if there is one.
+      if os.path.exists(persistentCache):
+        with open(persistentCache, 'rb') as cacheFile:
+          cache = pickle.load(cacheFile)
+
+      cacheKey = pickle.dumps(extractCacheKey(config, *args, **kwargs))
       if cacheKey not in cache:
-        cache[cacheKey] = function(*args, **kwargs)
+        cache[cacheKey] = function(config, *args, **kwargs)
+        # Update the persistent cache so it knows about the new key
+        with open(persistentCache, 'wb') as cacheFile:
+          pickle.dump(cache, cacheFile)
       return cache[cacheKey]
     return f
   return decorator


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D117361.400146.patch
Type: text/x-patch
Size: 2016 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20220114/1b86f13e/attachment.bin>


More information about the libcxx-commits mailing list