Skip to content

Cache structs.fields() result for non-generic structs#997

Closed
Siyet wants to merge 1 commit intojcrist:mainfrom
Siyet:963-cache-fields
Closed

Cache structs.fields() result for non-generic structs#997
Siyet wants to merge 1 commit intojcrist:mainfrom
Siyet:963-cache-fields

Conversation

@Siyet
Copy link
Copy Markdown
Collaborator

@Siyet Siyet commented Apr 1, 2026

Summary

  • Cache the fields() result tuple on the struct class as __struct_field_info__
  • Avoids expensive get_class_annotations() call and FieldInfo object recreation on every invocation
  • Generic aliases (e.g. MyStruct[int]) are not cached since type parameters affect annotations

Closes #963

Test plan

Ubuntu 22.04 (WSL2, x86_64, gcc 11.4, Python 3.10):

12 passed (TestInspectFields)
6130 passed, 70 skipped (full suite)

Ubuntu 24.04 (WSL2, x86_64, gcc 13.3, Python 3.12):

12 passed (TestInspectFields)

New tests:

  • test_fields_cached - second call returns the same object (is)
  • test_fields_cached_instance - class and instance share the same cache
  • test_fields_generic_not_cached_across_params - Example[str] and Example[int] return different results

Benchmark (1M calls, 3 fields):

Ubuntu 22.04, Python 3.10:

Before After
dataclasses.fields() 0.85s 0.85s
msgspec.structs.fields() ~7.5s (20x slower) 0.44s (2x faster)

Ubuntu 24.04, Python 3.12:

Before After
dataclasses.fields() 0.79s 0.79s
msgspec.structs.fields() ~7.5s (20x slower) 0.36s (2x faster)
  • CI passes on all platforms

Store the computed tuple of FieldInfo on the class as
__struct_field_info__ to avoid expensive get_class_annotations()
and FieldInfo recreation on every call. Generic aliases are not
cached since type parameters affect annotations.

Closes #963
@Siyet
Copy link
Copy Markdown
Collaborator Author

Siyet commented Apr 8, 2026

Resolved in the community fork msgspec-arise: PR #13, released in v0.20.2.

@Siyet Siyet closed this by deleting the head repository Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

msgspec.structs.fields() is 20x slower than dataclasses.fields()

1 participant