Publish Docker image variant with V8 pointer compression (-pc tags)#566
Publish Docker image variant with V8 pointer compression (-pc tags)#566kriszyp wants to merge 2 commits into
Conversation
…r#919) Adds a -pc image variant (harperfast/harper-pro:<version>-pc) whose runtime Node binary is compiled with V8 pointer compression: ~40% lower JS heap memory (43% measured on a 2M-object graph), 4 GB heap cap per isolate (per worker thread — Node uses per-isolate cages). The base image (harperfast/node-pointer-compression, built by the new dispatch-only publish-node-pc-image workflow so releases are not slowed by the 1-2h Node compile) also carries uWebSockets.js and @datadog/pprof binaries rebuilt against the pointer-compression V8 ABI — both link the raw V8 ABI (not Node-API) and their upstream prebuilds segfault on a pointer-compression node (verified live). The main Dockerfile swaps them in and marks the packages with .pointer-compression-build; version- specific direct-V8 addon variants (node.abi*.node) are dropped in favor of their Node-API builds; and a build-time ABI scan (check-native-abi-pointer-compression.js) fails the image if any raw-V8- ABI binary that could load on the runtime remains. analytics/profile.ts skips profiling with a warning (instead of crashing) on pointer-compression runtimes where pprof lacks the marker. All other production native modules (rocksdb-js, lmdb, msgpackr/cbor extract, argon2, bufferutil, utf-8-validate) are Node-API and unaffected; segfault-handler is source-built in-image and picks up the correct ABI from the running node. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces support for a Node.js runtime variant compiled with V8 pointer compression. It adds a dedicated Dockerfile to build the custom Node.js image, rebuilds incompatible native modules (uWebSockets.js and @datadog/pprof) against the pointer-compression ABI, and implements an ABI guard script to verify native module compatibility during the build. Additionally, the profiling logic is updated to safely disable profiling if pointer compression is active but the compatible @datadog/pprof binary is missing. Feedback on the changes highlights two key issues: first, the ABI guard script could silently bypass checks if the nm utility is missing from the system; second, using __filename in analytics/profile.ts will throw a ReferenceError in ES module environments, causing profiling to be silently disabled. Both comments provide actionable code suggestions to resolve these issues.
|
Reviewed; no blockers found. |
Per-file nm errors are tolerated (non-ELF files), so an absent nm binary would have silently passed the scan without checking anything. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Adds a pointer-compression variant of the Docker image —
harperfast/harper-pro:<version>-pc— whose runtime Node is compiled with--experimental-enable-pointer-compression: ~40% lower JS heap memory (43% measured on a 2M-object graph: 376→215 MB heapUsed; idle container RSS 2.07→1.7 GiB) with a 4 GB heap cap per isolate (per worker thread — Node uses per-isolate cages, and Harper's automatic worker heap sizing never exceeds 4 GB). For heap-bound edge deployments this is roughly a 40% density win. Closes HarperFast/harper#919.Pieces:
build-tools/node-pointer-compression.Dockerfile+publish-node-pc-image.yaml(dispatch-only): buildsharperfast/node-pointer-compression:<major>— the standard node image with the node binary rebuilt from source, plus uWebSockets.js and @datadog/pprof binaries rebuilt against the pointer-compression V8 ABI. Dispatch-only so the 1–2 h Node compile never slows a release; re-run when the Node version / uWS pin / pprof version bumps.Dockerfile: newRUN_IMAGEbuild arg; on a pointer-compression base, swaps in the rebuilt uWS + pprof binaries (with.pointer-compression-buildmarkers), drops version-specific direct-V8 addon variants (node.abi*.node) in favor of their Node-API builds, and fails the build if any raw-V8-ABI binary that could load on the runtime remains (build-tools/check-native-abi-pointer-compression.js).publish-docker.yaml: explicit build matrix with pc legs (default Node version only) and amerge-pcjob pushing-pctags, with a release-time assertion that pointer compression is on and the rebuilt uWS constructs in the pushed image.analytics/profile.ts: on a pointer-compression runtime without the pprof marker, profiling is skipped with a warning instead of crashing.Why the uWS/pprof rebuilds are necessary
Both link the raw V8 C++ ABI (not Node-API); their upstream prebuilds load cleanly on a pointer-compression node and then segfault on first use — both verified live (pprof crashed PID 1 at boot +1s;
uWS.App()SIGSEGVs). The pointer-compression ABI is set by header-level defines, so rebuilding with matching defines fixes them: uWS follows its ownbuild.crecipe with the PC defines added; pprof is built from the DataDog/pprof-nodejs repo (its npm package ships no C++ sources) simply by running node-gyp under the pointer-compression node — node-gyp derives its defines from the running node'sprocess.config, which is also why in-image source-built addons (segfault-handler) are automatically correct. All other production native modules (rocksdb-js, lmdb, msgpackr/cbor-extract, argon2, bufferutil, utf-8-validate) are Node-API and unaffected.Validated end-to-end (local amd64 builds)
Booted the pc image with
HARPER_UWS_HTTP=trueand a 15 s profiling capture period: uWS serves (uWebSockets: 20response header), profiler captures repeatedly, insert/read green, no segfaults; negative test (marker removed) degrades to a per-worker warning with the instance healthy.Attention / open items
PPROF_VERSION(package-lock) andUWS_SOURCE_COMMIT(thesource_commitfile inside the pinned uWS binaries tarball).node.abi*.node) for its Node-API build.node:24(bookworm); once fix: base Docker image on Debian trixie for uWebSockets.js glibc 2.38 #564 (trixie) lands it should follow — the pc variant is glibc-self-consistent either way since its V8-ABI addons are compiled in-image.tscreportsNumeric-vs-numbererrors inanalytics/profile.tssample processing (pprof-format types); the package build does not gate on them.🤖 Generated with Claude Code (Fable 5)