Skip to content

Significantly optimise checking of repeatedly-instantiated TypedDict objects - #4489

Open
alexander-beedie wants to merge 1 commit into
facebook:mainfrom
alexander-beedie:perf-typed-dicts
Open

Significantly optimise checking of repeatedly-instantiated TypedDict objects#4489
alexander-beedie wants to merge 1 commit into
facebook:mainfrom
alexander-beedie:perf-typed-dicts

Conversation

@alexander-beedie

@alexander-beedie alexander-beedie commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Identified a somewhat niche hotspot relating to TypedDict; with this PR in place, type-checking pydantic gets ~2x faster (measured ~60% less CPU time), and two other packages get a ~6-10% improvement. Pretty much a no-op otherwise.

Problem

Instantiating TypedDict fields rebuilt a full SmallMap of field types on every call, with each rebuild deep-copying every field type; callers that only iterate paid that cost repeatedly.

Solution

  • Cache the instantiated field map per Solver, in such a way that repeat calls share one allocation (instead of re-cloning each field's type tree).
  • Only cache what is context-independent (mirrors the existing protocol_cache rule of caching only Var-free types).
  • Never cache an incomplete map (field lookup failures are now classified: see FieldOutcome).
  • Fixed InitVar on a TypedDict member (it's not valid and blocked caching).
  • Don't clone ClassField just to read it.

Test Plan

All existing unit tests pass without modification.
Several new unit tests added.

Benchmarks1

Huge positive impact on pydantic (the pydantic_core.core_schema module is an absolute wall of TypedDict) 🚀

The speedup tracks with repeated instantiation of the same TypedDict, not the overall TypedDict count, and it seems that's not a common pattern; only a couple of packages show much benefit (aside from pydantic the only other solid gains I spotted are for numpy and narwhals, which both get a bit faster).

CPU time (user+sys)

My machine was a bit contended, so I recorded CPU-time instead of wall-clock as it was much more stable (measurements are standard multithreaded runs):

project before after Δ
pydantic 3.71s 1.53s −58.7%
numpy 12.01s 11.08s −6.9%
narwhals2 2.36s 2.18s −7.9%

Footnotes

  1. Test machine: Apple Silicon M3 Max (16 cores).

  2. @MarcoGorelli, "you're welcome" 🤣

@meta-cla meta-cla Bot added the cla signed label Aug 9, 2026
@alexander-beedie alexander-beedie changed the title Significantly optimise checking of repeatedly-instantiated TypedDicts Significantly optimise checking of repeatedly-instantiated TypedDicts objects Aug 9, 2026
@alexander-beedie alexander-beedie changed the title Significantly optimise checking of repeatedly-instantiated TypedDicts objects Significantly optimise checking of repeatedly-instantiated TypedDict objects Aug 9, 2026
@meta-codesync

meta-codesync Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D115363524. (Because this pull request was imported automatically, there will not be any future comments.)

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@yangdanny97

Copy link
Copy Markdown
Contributor

@samwgoldman

@yangdanny97

Copy link
Copy Markdown
Contributor

TypedDict stuff would normally be under my wheelhouse but I don't have any capacity in the near future so I'll let Sam handle this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants