Repository navigation
test(perf-proofs): prove null-prototype entities are slower, not faster - #14
Merged
Merged
Conversation
Adds null-proto-vs-plain benchmark testing the claim from https://adventures.nodeland.dev/archive/optimizing-objects-with-null-prototypes/. Null-prototype objects start in V8 dictionary mode, so `{ __proto__: null }` and `Object.create(null)` entities are 6-15x slower to iterate and archetype-match than plain literals — the same dictionary-mode penalty as `delete`. `setPrototypeOf(obj, null)` keeps fast properties (reads fastest of the three) but is 74x slower to create. Measured on Node 26.11.1. Isolating each kind in its own monomorphic access site barely moved the gap (iteration 8.5x -> 6.6x), confirming dictionary mode, not megamorphism, is the dominant cost. Documents the finding as a CLAUDE.md convention alongside the existing delete-vs-set-undefined / ADR 0001 guidance. No core lib change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The comment claimed objecs uses `delete` in removeEntityComponents; ADR 0001 reversed that to `= undefined`. Fixes the comment to match current behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
✅ Deploy Preview for objecs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Investigates the null-prototype optimization from this nodeland.dev article against the objecs core lib, and lands the finding as a perf-proofs benchmark + a CLAUDE.md convention.
Finding: null-prototype entities are slower, not faster
The article's counterintuitive claim holds and applies directly to objecs's hot path.
{ __proto__: null }andObject.create(null)start in V8 dictionary mode (hash-table props, no hidden class / inline caches), and reads never restore fast mode. Measured on Node 26.11.1 (Ryzen 9 7950X3D), plain literal = baseline:{ __proto__: null }Object.create(null)setPrototypeOf(obj, null)setPrototypeOf(obj, null)keeps fast properties (reads fastest of the three null-proto forms) but thesetPrototypeOfcall makes it the slowest to create — only worth it for long-lived, read-many objects, never per-frame churn.Core lib impact: none to fix, but it validates ADR 0001
The core lib creates zero null-prototype objects (it uses
Map/Setfor lookups, plain arrays for storage), so there is no speedup to extract — the article instead independently confirms the dictionary-mode reasoning behind ADR 0001 (= undefinednotdelete). This is user-facing guidance: a user reaching for null-proto entities would quietly take a 6–15× hit.Changes
test(perf-proofs):null-proto-vs-plain.ts— creation / iteration / presence across all four construction styles, with monomorphic per-kind access sites to isolate dictionary mode from megamorphism. Plus CLAUDE.md convention + perf-proofs README entry.docs(perf-proofs):fix a stale comment indelete-vs-set-undefined.tsthat still claimed objecs usesdelete(ADR 0001 reversed that).Verification
pnpm lint✅ · perf-proofs typecheck ✅ · both object benchmarks run clean. No core objecs API or behavior change.🤖 Generated with Claude Code