Skip to content

Commit db3754f

Browse files
committed
add cache for options snapshot
1 parent be46935 commit db3754f

1 file changed

Lines changed: 20 additions & 6 deletions

File tree

mypy/build.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,11 @@ def __init__(
993993
self.import_options: dict[str, bytes] = {}
994994
# Cache for transitive dependency check (expensive).
995995
self.transitive_deps_cache: dict[tuple[int, int], bool] = {}
996+
# Cache for options_snapshot() keyed by id() of the cloned Options.
997+
# Most modules share a handful of distinct configs. The keepalive
998+
# list keeps clones reachable so id() is stable for cache keys.
999+
self.options_snapshot_cache: dict[int, tuple[str, str]] = {}
1000+
self._options_snapshot_keepalive: list[Options] = []
9961001
# Packages for which we know presence or absence of __getattr__().
9971002
self.known_partial_packages: dict[str, bool] = {}
9981003

@@ -1966,23 +1971,32 @@ def get_cache_names(id: str, path: str, options: Options) -> tuple[str, str, str
19661971
return prefix + meta_suffix, prefix + data_suffix, deps_json
19671972

19681973

1969-
def options_snapshot(id: str, manager: BuildManager) -> dict[str, object]:
1974+
def options_snapshot(module: str, manager: BuildManager) -> dict[str, object]:
19701975
"""Make compact snapshot of options for a module.
19711976
19721977
Separately store only the options we may compare individually, and take a hash
19731978
of everything else. If --debug-cache is specified, fall back to full snapshot.
19741979
"""
1975-
platform_opt, values = manager.options.clone_for_module(id).select_options_affecting_cache()
1980+
cloned = manager.options.clone_for_module(module)
19761981
if manager.options.debug_cache:
19771982
# Build full options snapshot for debugging purposes.
1983+
platform_opt, values = cloned.select_options_affecting_cache()
19781984
result: dict[str, object] = {"platform": platform_opt}
19791985
for key, val in zip(OPTIONS_AFFECTING_CACHE_NO_PLATFORM, values):
19801986
result[key] = val
19811987
return result
1982-
# Process most options quickly, since this is performance critical.
1983-
buf = WriteBuffer()
1984-
write_json_value(buf, cast(JsonValue, values))
1985-
return {"platform": platform_opt, "other_options": hash_digest(buf.getvalue())}
1988+
cache = manager.options_snapshot_cache
1989+
key = id(cloned)
1990+
cached = cache.get(key)
1991+
if cached is None:
1992+
platform_opt, values = cloned.select_options_affecting_cache()
1993+
buf = WriteBuffer()
1994+
write_json_value(buf, cast(JsonValue, values))
1995+
cached = (platform_opt, hash_digest(buf.getvalue()))
1996+
cache[key] = cached
1997+
# Keep cloned reachable so its id() is not reused by a later clone.
1998+
manager._options_snapshot_keepalive.append(cloned)
1999+
return {"platform": cached[0], "other_options": cached[1]}
19862000

19872001

19882002
def find_cache_meta(

0 commit comments

Comments
 (0)