Skip to content

Commit e7da3b4

Browse files
committed
chore: handover — bson-js v7 upgrade, PR description as Deepkit v2
Next steps: - Investigate BSON deserialize perf ceiling (only 5-13x vs bson-js v7) - Fix consumer BSON imports (rpc, mongo, broker, framework-debug-api) - Commit as proper semantic commits when ready Handover document: .claude/handover.md
1 parent 1b1ebe9 commit e7da3b4

30 files changed

+5897
-4423
lines changed

.claude/handover.md

Lines changed: 62 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Handover
22

3-
*Updated 2026-02-08 (Gen 70)*
3+
*Updated 2026-02-08 (Gen 71)*
44

55
## Init Checklist
66
<!-- Next agent: complete these steps IN ORDER before doing anything else. -->
77
1. Read this entire handover document
88
2. Read `CLAUDE.md` for project rules
9-
3. Read `docs/pr-description.md` — comprehensive PR description with all changes cataloged
9+
3. Read `docs/pr-description.md` — comprehensive PR description with all changes cataloged (now titled "Deepkit v2")
1010
4. Run the verification command (below) to confirm expected state
1111
5. Recreate tasks from the Tasks section via `TaskCreate`
1212
6. Check the Suppressed Issues section — do not re-suppress these without noting it
@@ -30,77 +30,69 @@ Test migration: Jest → node:test + @deepkit/run/expect shim
3030
## Current State
3131
- **Branch**: `feat/next`
3232
- **Backup branch**: `feat/next-backup` (points to pre-perf-fix state, 306+ messy commits)
33-
- **Active plan**: none — commit plan executed, PR description updated
34-
- **Working on**: Consumer package migration (broken BSON imports) + performance verification
35-
- **Dirty files**: none (all committed)
36-
- **Failing tests**: none known for bson/type/type-compiler — consumer packages (rpc, mongo, broker, framework-debug-api) have broken BSON imports that will fail at compile
33+
- **Active plan**: none
34+
- **Working on**: BSON deserialize performance investigation (user wants >13x vs bson-js)
35+
- **Dirty files**: uncommitted — bson v7 upgrade, PR description update (29 files, see git diff --stat)
36+
- **Failing tests**: none known for bson/type/type-compiler. Consumer packages (rpc, mongo, broker, framework-debug-api) have broken BSON imports (deferred to separate session).
3737
- **Master worktree**: `/Users/marc/bude/deepkit-master` — fully built, has compiled benchmarks (`packages/bson/tsconfig.bench.json``dist/bench/`)
38-
- **Verification command**: `git log --oneline -5` (expect: 21 semantic commits, top is `chore: update handover...`, below it `docs(website)...`, `fix: update remaining packages...`, etc.)
38+
- **Verification command**: `git diff --stat` (expect: 29 files changed — bson v7 upgrade + PR description updates)
3939

4040
## Next Steps
41-
1. **Prove performance is still optimal** — Run BSON and type benchmarks vs master and bson vs bson-js. bson-js should be updated to newest version first. Benchmark files:
42-
- feat/next perf-regression: `node --import @deepkit/run --test packages/bson/tests/serialize/perf-regression.spec.ts` and `tests/deserialize/perf-regression.spec.ts`
43-
- master comparison: `cd /Users/marc/bude/deepkit-master && npx tsc -p packages/bson/tsconfig.bench.json && node --expose-gc packages/bson/dist/bench/benchmarks/compare-bench.js`
44-
- type benchmarks: `packages/type/benchmarks/compare-bench.ts` (feat/next), master has equivalent in its worktree
45-
2. **Fix consumer package BSON imports** — See Suppressed Issues for the full list. Key broken packages: rpc, mongo, broker, broker-redis, framework-debug-api. See `docs/pr-description.md` "Open TODOs" section for migration details.
46-
3. **Verify final state** — Full test suite must pass after consumer migrations
41+
1. **Investigate BSON deserialize performance ceiling** — Currently only 5–13x faster than bson-js v7 for deserialization. User considers this insufficient. Compare against manually-written optimal deserializer to find bottleneck. Key benchmarks: `packages/bson/tests/deserialize/perf-regression.spec.ts`. Profile shape JIT code path for overhead.
42+
2. **Fix consumer package BSON imports** — Key broken packages: rpc, mongo, broker, broker-redis, framework-debug-api. See Suppressed Issues for file locations. See `docs/pr-description.md` "Open TODOs" for migration details. (User said: do in separate session)
43+
3. **Commit the dirty files** — bson v7 upgrade + PR description updates need to be committed.
4744

4845
## Alignment Check
49-
- **Goal**: Get feat/next branch ready for PR — all tests passing, performance proven, clean commit history
50-
- **Scope boundary**: The commit plan is DONE (21 commits). Focus is now on (a) proving perf is optimal, (b) fixing broken consumer imports. Do NOT re-squash commits.
51-
- **Plan file**: none — commit plan was executed this session
46+
- **Goal**: Get feat/next branch ready as Deepkit v2 — all tests passing, performance maximized, clean history
47+
- **Scope boundary**: Consumer package migration is deferred. Do NOT re-squash commits. Focus is on (a) deserialize perf investigation, (b) eventually fixing consumer imports.
48+
- **Plan file**: none
5249
- **Recovery**: `git reset --hard feat/next-backup` restores the 306+ commit history (loses clean squash)
5350

5451
## Tasks
55-
- [ ] **Update bson-js to latest version** — Check if `bson` npm package in the repo is latest. Update and re-run comparison benchmarks. [status: pending]
56-
- [ ] **Run BSON perf benchmarks vs master** — Run both serialize and deserialize perf-regression tests on feat/next AND master compare-bench.ts. Verify all ratios hold. [status: pending]
57-
- [ ] **Run type perf benchmarks vs master** — Ensure all 12 type benchmarks still beat master. [status: pending]
58-
- [ ] **Fix consumer BSON imports (rpc)**`packages/rpc/src/protocol.ts` uses Writer, getBSONSizer, BsonStreamReader. Needs refactored message construction. HIGH complexity. [status: pending]
59-
- [ ] **Fix consumer BSON imports (mongo)**`packages/mongo/src/client/connection.ts` uses BSONBinarySerializer, Writer, getBSONSizer. Needs new serializer composition. HIGH complexity. [status: pending]
60-
- [ ] **Fix consumer BSON imports (broker)**`packages/broker/src/snapshot.ts` uses old getBSONSerializer return type. `packages/broker/src/adapters/deepkit-adapter.ts` uses getBsonEncoder. LOW complexity. [status: pending]
61-
- [ ] **Fix consumer BSON imports (broker-redis)** — Remove AutoBuffer, fix getBsonEncoder → getBSONEncoder. MEDIUM complexity. [status: pending]
52+
- [ ] **Investigate BSON deserialize perf ceiling** — Deserialize is only 5–13x vs bson-js v7 (serialize is 2–224x). Write a manually-optimized deserializer for a sensor doc to find theoretical max, then compare with generated JIT code. Identify specific overhead sources. [status: pending]
53+
- [ ] **Commit bson v7 upgrade + PR description updates** — 29 dirty files. bson ^4.4.0 → ^7.2.0, 26 test import fixes, 4 threshold adjustments, PR description rewrite. [status: pending]
54+
- [ ] **Fix consumer BSON imports (rpc)**`packages/rpc/src/protocol.ts` uses Writer, getBSONSizer, BsonStreamReader. HIGH complexity. [status: pending]
55+
- [ ] **Fix consumer BSON imports (mongo)**`packages/mongo/src/client/connection.ts` uses BSONBinarySerializer, Writer, getBSONSizer. HIGH complexity. [status: pending]
56+
- [ ] **Fix consumer BSON imports (broker + broker-redis)** — broker: tuple destructure, renamed encoder. broker-redis: remove AutoBuffer, fix case. LOW-MEDIUM complexity. [status: pending]
6257
- [ ] **Fix consumer BSON imports (framework-debug-api)**`packages/framework-debug-api/src/stopwatch-encoding.ts` uses Writer, BaseParser, getBSONSizer, stringByteLength. MEDIUM complexity. [status: pending]
6358

6459
## Benchmark Data
6560

66-
### @deepkit/bson: perf-regression results (Gen 70, fresh run)
67-
68-
**Serialize (feat/next vs bson-js):**
69-
70-
| Benchmark | Ops/sec | vs bson-js |
71-
|-----------|---------|------------|
72-
| int32 | 1,174M | 301x |
73-
| sensor (4 numeric) | 336M | 193x |
74-
| user profile (6 fields) | 16.6M | 16x |
75-
| API meta (3 strings) | 15.9M | 8x |
76-
| sensor[] 10 cursor | 8.7M | 46x |
77-
| sensor[] 1K cursor | 100K | 43x |
78-
| mixed[] 10 cursor | 1.9M | 15x |
79-
| mixed[] 1K cursor | 20K | 14x |
80-
81-
**Deserialize (feat/next vs bson-js):**
82-
83-
| Benchmark | Ops/sec | vs bson-js |
84-
|-----------|---------|------------|
85-
| int32 | 187M | 31x |
86-
| sensor (4 numeric) | 23M | 12x |
87-
| user profile (6 fields) | 11.5M | 12x |
88-
| API meta (3 strings) | 13.1M | 8x |
89-
| sensor[] 10 cursor | 1.7M | 11x |
90-
| sensor[] 1K cursor | 17K | 10x |
91-
| mixed[] 10 cursor | 1.0M | 10x |
92-
| mixed[] 1K cursor | 10K | 10x |
93-
94-
**Master comparison (from same-session run):**
95-
96-
| Benchmark | master | feat/next | Improvement |
97-
|-----------|--------|-----------|-------------|
98-
| ser sensor | 7.5M | 336M | 45x |
99-
| ser sensor[]10 cursor | 758K | 8.7M | 11x |
100-
| ser sensor[]1K cursor | 8.4K | 100K | 12x |
101-
| des sensor | 13.1M | 23M | 1.8x |
102-
| des sensor[]10 cursor | 1.5M | 1.7M | 1.1x |
103-
| des sensor[]1K cursor | 16.6K | 17K | ~same |
61+
### Fresh clean-run numbers (Gen 71, sequential, bson-js 7.x)
62+
63+
**BSON Serialize (key benchmarks):**
64+
65+
| Benchmark | v2 ops/sec | vs v1 | vs bson-js 7.x |
66+
|-----------|-----------|-------|----------------|
67+
| int32 | 1,198M | 63x | 203x |
68+
| sensor (4 numeric) | 342M | 46x | 153x |
69+
| user profile (6 fields) | 16.8M | 3.4x | 10x |
70+
| API meta (3 strings) | 16.0M | 3.3x | 7x |
71+
| UUID | 24.9M | 4.0x | 6x |
72+
| sensor[] 10 cursor | 8.7M | 11.6x | 39x |
73+
| string[] 100 | 700K || 2x |
74+
75+
**BSON Deserialize (key benchmarks):**
76+
77+
| Benchmark | v2 ops/sec | vs v1 | vs bson-js 7.x |
78+
|-----------|-----------|-------|----------------|
79+
| int32 | 186M | 6.5x | 13x |
80+
| sensor (4 numeric) | 23.3M | 1.8x | 10x |
81+
| user profile (6 fields) | 11.6M || 7x |
82+
| API meta (3 strings) | 12.7M | 3.4x | 6x |
83+
| UUID | 17.6M | 3.5x | 5x |
84+
| sensor[] 10 cursor | 1.7M | 1.1x | 7.5x |
85+
| string[] 100 | 500K || 2.5x |
86+
87+
**Type (fn() API, all 12 beat v1):**
88+
89+
| Benchmark | v2 | v1 | Change |
90+
|-----------|------|------|--------|
91+
| Small serialize | 135.6M | 19.0M | +614% |
92+
| Union serialize | 34.0M | 2.4M | +1317% |
93+
| Small validate | 64.8M | 20.4M | +218% |
94+
| Union validate | 8.4M | 0.5M | +1580% |
95+
| Small is() | 374.2M | 21.1M | +1674% |
10496

10597
## Learnings
10698
-[2026-02-06] **Type compiler resolves `T | undefined` as optional T, not union**`prop.optional = true` and `prop.type = UUID`.
@@ -110,9 +102,10 @@ Test migration: Jest → node:test + @deepkit/run/expect shim
110102
-[2026-02-08] **`getBSONSerializer` returns `[sharedBuffer, size]` — buffer is reused across ALL serializers globally**. Callers must copy with `buf.slice(0, size)`.
111103
-[2026-02-08] **BSONBuildState `forIndex()` must NOT increment depth** — Incrementing depth caused extraction at MAX_DEPTH=3, 60-90x slower for cursor responses.
112104
-[2026-02-08] **Shape JIT must handle primitive arrays** — Without inline, documents with `string[]`/`number[]` cause shape JIT BAILOUT.
113-
-[2026-02-08] **BenchSuite executor does NOT prevent V8 dead-code elimination** — Use `sink` variable.
114-
-[2026-02-08] **Master BSON benchmark needs compiled JS**`tsconfig.bench.json` with `"reflection": true`, compile with tsc, run from `dist/bench/`.
115-
- ⚠️ [2026-02-08] **BSON array deserialize improvement limited at scale** — Single-doc sensor 1.8x faster, but sensor[]1K cursor ~same speed. Setup/overhead improvement is amortized; per-element byte-reading cost is similar between branches (~55-60ns/sensor). Serialize arrays DO scale (12x faster) due to buffer reuse.
105+
-[2026-02-08] **BSON array deserialize improvement limited at scale** — Per-element cost ~55-60ns on both branches. Setup overhead amortized across 1000 elements.
106+
- ⚠️ [2026-02-08] **bson-js v7 dropped default export** — Must use `import * as bson from 'bson'` instead of `import bson from 'bson'`. Also removed `@types/bson` (v7 ships own types).
107+
- ⚠️ [2026-02-08] **bson-js v7 is 2–5x faster than v4** — Our absolute perf unchanged, but comparison ratios drop. Thresholds in perf-regression tests adjusted.
108+
- ⚠️ [2026-02-08] **bson-js has no pre-allocated buffer API**`serialize()` always allocates `Buffer.allocUnsafe()`. No `serializeInto()`. Buffer alloc + GC is their top overhead for small docs (~50-80ns).
116109

117110
## Dead Ends
118111
- [2026-02-04] **"Assumed order" fast-path** — WRONG for MongoDB which returns arbitrary field order.
@@ -129,9 +122,10 @@ Test migration: Jest → node:test + @deepkit/run/expect shim
129122
- [2026-02-07] `packages/broker/src/snapshot.ts` — Uses `getBSONSerializer` return as `Uint8Array` (actually `[Uint8Array, number]`). Will fail at runtime.
130123
- [2026-02-07] `packages/broker/src/adapters/deepkit-adapter.ts` — Uses `getBsonEncoder` (renamed). Will fail at compile.
131124
- [2026-02-08] `packages/type/tests/serializer.spec.ts:1153,1180,1204,1363` — 4 tests skipped (`test.skip`): onLoad call (x3), extend with custom type. Pre-existing Jest skips.
125+
- [2026-02-08] `packages/bson/tests/deserialize/perf-regression.spec.ts` — 4 thresholds lowered for bson v7: boolean 5→1.5, number 2→1, UUID (ser) 5→2, string[] (ser) 3→1.5. Not regressions — bson-js v7 is faster.
132126

133127
## Open Questions
134-
- **BSON array deserialize does NOT benefit from single-doc speedup**Per-element cost ~55-60ns on both branches. Setup overhead (33ns improvement) is amortized across 1000 elements. Optimization target: investigate if shape JIT can reduce per-element overhead for array deserialization.
128+
- **Why is BSON deserialize only 5–13x vs bson-js v7?**Serialize is 2–224x faster, but deserialize ceiling is 13x. User considers this unacceptable. Need to profile the generated JIT code against a hand-written optimal deserializer to identify specific bottlenecks. Potential areas: shape JIT overhead, field name parsing, object allocation, property assignment.
135129

136130
## Generation Log
137131
- [2026-02-04] Gen 1-35: BSON rewrite foundations
@@ -151,7 +145,8 @@ Test migration: Jest → node:test + @deepkit/run/expect shim
151145
- [2026-02-08] Gen 67: Inlined index signatures. ALL 12 type benchmarks beat master.
152146
- [2026-02-08] Gen 68: Ran BSON benchmarks. Found shared-buffer corruption bug in benchmarks. Fixed: all 22 BSON benchmarks beat master. Fixed bson-js comparison benchmark for new API.
153147
- [2026-02-08] Gen 69: Fixed BSON array perf — 60-90x improvement. Deepkit 6-12x faster than bson-js at ALL sizes.
154-
- [2026-02-08] Gen 70: Ran all 53 BSON perf-regression tests (pass). Ran master comparison benchmarks. Updated PR description with 3 numbers per benchmark (ops/sec, vs master, vs bson-js). Executed commit plan — squashed 306+ commits into 21 clean semantic commits. Discovered array deserialize does not scale with single-doc improvement.
148+
- [2026-02-08] Gen 70: Executed commit plan — squashed 306+ commits into 21 clean semantic commits.
149+
- [2026-02-08] Gen 71: Updated bson-js v4→v7. Fixed 26 test imports, adjusted 4 thresholds. Rewrote PR description as "Deepkit v2" with performance summary. All benchmarks re-run sequentially with clean numbers. User flagged deserialize perf ceiling for investigation.
155150

156151
---
157-
*End of handover. Next: prove perf is optimal (update bson-js, re-run benchmarks), then fix consumer BSON imports.*
152+
*End of handover. Next: investigate BSON deserialize perf ceiling, then fix consumer BSON imports.*

0 commit comments

Comments
 (0)