[PR #994] [MERGED] perf(domain): batch canonical digest writes with bounded buffer #2563

Closed
opened 2026-10-17 21:07:37 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/994
Author: @HoneyTyagii
Created: 10/7/2026
Status: ✅ Merged
Merged: 10/7/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: perf/canonical-digest-batching-904


📝 Commits (1)

  • dca1490 perf(domain): batch canonical digest writes with bounded buffer

📊 Changes

2 files changed (+19 additions, -1 deletions)

View changed files

📝 src/domain/canonicalDigest.test.ts (+7 -0)
📝 src/domain/canonicalDigest.ts (+12 -1)

📄 Description

Summary

Closes #904.

Batch small canonical parts before calling crypto hash update, while preserving the exact canonical byte stream and streaming memory bound.

Problem and expected behavior

A native Node CPU profile of analyze-javascript-application dist/server shows about 44.8 percent of sampled frames in hash.update plus emitCanonical:

  • update in node:internal/crypto/hash: 1,053 self samples
  • emitCanonical in dist/domain/canonicalDigest.js: 924 self samples
  • Total 1,977 of 4,409 exported samples

src/domain/canonicalDigest.ts calls emitCanonical(value, part => hash.update(part), ...) where punctuation, keys, and scalars each trigger a separate native crossing. This preserves the streaming bound added after #623 but adds per token overhead.

Expected: same digests with fewer hash updates, no full graph string in memory.

Changes

  • Add bounded buffering in digestCanonicalValue: accumulate emitted parts in a string buffer up to 8 KB, flush with hash.update, flush remainder before digest.
  • Keep emitCanonical recursion, validation, and failure behavior unchanged, including Unicode, sparse arrays, unsupported values, toJSON, invalid numbers, and cycles.
  • Add regression coverage in src/domain/canonicalDigest.test.ts:
    • digest equivalence against canonicalize for existing fixtures
    • update call count drops on a wide object while digest stays identical

Verification

  • npx vitest run src/domain/canonicalDigest.test.ts: 6 passed
  • Manual equivalence check against canonicalize for JSON values and prior edge fixtures
  • Follow up per #904: isolated repeat of the same dist/server analysis with CPU and heap profiles, elapsed samples, and peak RSS before claiming speedup

Risk

Low. Byte stream is unchanged, only grouping of hash writes changes. Failure paths and digest mismatch errors stay the same. Related: #623, #723.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/994 **Author:** [@HoneyTyagii](https://github.com/HoneyTyagii) **Created:** 10/7/2026 **Status:** ✅ Merged **Merged:** 10/7/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `perf/canonical-digest-batching-904` --- ### 📝 Commits (1) - [`dca1490`](https://github.com/morluto/rea/commit/dca14900c4746153555d4c1b805324b1397a452a) perf(domain): batch canonical digest writes with bounded buffer ### 📊 Changes **2 files changed** (+19 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `src/domain/canonicalDigest.test.ts` (+7 -0) 📝 `src/domain/canonicalDigest.ts` (+12 -1) </details> ### 📄 Description ## Summary Closes #904. Batch small canonical parts before calling crypto hash update, while preserving the exact canonical byte stream and streaming memory bound. ## Problem and expected behavior A native Node CPU profile of `analyze-javascript-application dist/server` shows about 44.8 percent of sampled frames in `hash.update` plus `emitCanonical`: - `update` in `node:internal/crypto/hash`: 1,053 self samples - `emitCanonical` in `dist/domain/canonicalDigest.js`: 924 self samples - Total 1,977 of 4,409 exported samples `src/domain/canonicalDigest.ts` calls `emitCanonical(value, part => hash.update(part), ...)` where punctuation, keys, and scalars each trigger a separate native crossing. This preserves the streaming bound added after #623 but adds per token overhead. Expected: same digests with fewer hash updates, no full graph string in memory. ## Changes - Add bounded buffering in `digestCanonicalValue`: accumulate emitted parts in a string buffer up to 8 KB, flush with `hash.update`, flush remainder before `digest`. - Keep `emitCanonical` recursion, validation, and failure behavior unchanged, including Unicode, sparse arrays, unsupported values, `toJSON`, invalid numbers, and cycles. - Add regression coverage in `src/domain/canonicalDigest.test.ts`: - digest equivalence against `canonicalize` for existing fixtures - update call count drops on a wide object while digest stays identical ## Verification - `npx vitest run src/domain/canonicalDigest.test.ts`: 6 passed - Manual equivalence check against `canonicalize` for JSON values and prior edge fixtures - Follow up per #904: isolated repeat of the same `dist/server` analysis with CPU and heap profiles, elapsed samples, and peak RSS before claiming speedup ## Risk Low. Byte stream is unchanged, only grouping of hash writes changes. Failure paths and digest mismatch errors stay the same. Related: #623, #723. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:07:37 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#2563
No description provided.