feat: add __slots__ to istr for lower memory use - #1386
Conversation
istr __slots__ to avoid per-key __dict__ (issue aio-libs#1360)
Vizonex
left a comment
There was a problem hiding this comment.
@ltsyk This looks way better than the last PR related to this one that I went through a while back. The workflows are failing however something I would recommend you try and do is run the tests locally when everything is considered as passing.
Merging this PR will degrade performance by 20.81%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ❌ | test_iterate_multidict[ci-py] |
547.1 µs | 771 µs | -29.04% |
| ❌ | test_iterate_multidict_keys[ci-py] |
556 µs | 767.1 µs | -27.51% |
| ❌ | test_iterate_multidict_items[ci-py] |
590.1 µs | 808.5 µs | -27.01% |
| ❌ | test_keys_view_less_or_equal[ci-py] |
612.3 µs | 832.5 µs | -26.45% |
| ❌ | test_keys_view_less[ci-py] |
629.6 µs | 845.6 µs | -25.54% |
| ❌ | test_items_view_less[ci-py] |
709.6 µs | 947.6 µs | -25.11% |
| ❌ | test_items_view_less_or_equal[ci-py] |
704.6 µs | 933.6 µs | -24.52% |
| ❌ | test_multidict_popitem_str[ci-py] |
1.5 ms | 1.7 ms | -14.21% |
| ❌ | test_keys_view_sub[ci-py] |
2.3 ms | 2.7 ms | -13.8% |
| ❌ | test_keys_view_or[ci-py] |
2.5 ms | 2.8 ms | -12.63% |
| ❌ | test_items_view_or[ci-py] |
2.7 ms | 3.1 ms | -10.77% |
| ❌ | test_keys_view_is_disjoint[ci-py] |
1.7 ms | 1.9 ms | -9.23% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing ltsyk:feat/istr-empty-slots (32e125a) with master (957def7)
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1386 +/- ##
=======================================
Coverage 99.86% 99.86%
=======================================
Files 28 28
Lines 3627 3647 +20
Branches 265 265
=======================================
+ Hits 3622 3642 +20
Misses 3 3
Partials 2 2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
PR Review — feat: add slots to istr for lower memory useGood, focused change; the Strengths:
Needs attention:
🟡 Important
1. Old protocol 0/1 pickles unpickle to an istr with an uninitialized slot
|
Vizonex
left a comment
There was a problem hiding this comment.
Looks good, would recommend you re-run pre-commit locally on your system and make a new commit once fully fixed but other than that this is perfect.
|
Thanks for reviewing. I reran the complete local test suite across both backends (1,409 passed), MyPy, and all pre-commit hooks; all pass and produced no changes, so there is no follow-up formatting commit to push. The GitHub Actions matrix is also green; the remaining pre-commit.ci status is its mergeable-check service error rather than a hook failure. |
Protocol 0/1 unpickling bypasses istr.__new__; use getattr in _identity and test that loaded istr works as a CIMultiDict key.
|
Thanks @Vizonex — rebased and addressed the remaining pure-Python edge case: Protocol 0/1 unpickling of older Pre-commit / suite re-checked on this tip. |
Confidence Score: 4/5Not safe to merge until the pure-Python The failure was reproduced with valid byte inputs and compared directly against builtin Files Needing Attention:
What T-Rex did
Comments Outside Diff (1)
Reviews (1): Last reviewed commit: "Merge branch 'master' into feat/istr-emp..." | Re-trigger Greptile |
| __is_istr__ = True | ||
| __istr_identity__: str | None = None | ||
|
|
||
| def __new__(cls, value: object = "") -> Self: |
There was a problem hiding this comment.
Pure-Python constructor drops encoding arguments
The narrowed __new__ signature rejects valid byte-decoding calls before it can delegate to str: istr(b"caf\xe9", "latin-1") and istr(b"a\xff", "ascii", "replace") raise TypeError. Builtin str and the C-extension istr decode the same values successfully. Accept and forward encoding and errors so callers receive the same result regardless of which multidict implementation is installed.
Context Used: CLAUDE.md (source)
Artifacts
Authored istr bytes constructor runtime review script
- The executed review script compares builtin str, pure-Python istr, and the available C-extension istr for valid bytes decoding inputs, providing the reproducible check.
Runtime comparison showing pure-Python istr TypeError while str and C istr decode
- Captured output of the authored comparison script shows both pure-Python TypeErrors and successful expected decoding by builtin str and C istr, verifying the incompatibility.
C-extension istr bytes decoding baseline
- Captured direct C-backend execution successfully decodes the same Latin-1 and ASCII-replace byte inputs, establishing the compatible backend baseline.
asvetlov
left a comment
There was a problem hiding this comment.
The pure-python istr deliberately doesn't use slots for the sake of performance; it is an aware memory-speed tradeoff.
Benchmarks show this choice clearly.
I doubt that we have to change the design decision.
Thoughts?
Summary
Add
__slots__foristrso case-insensitive keys do not allocate a per-instance__dict__(issue #1360).Fixes #1360