Files
HealthLog/scripts/bench/results/v1.45.0-before-boot.md
T
Marc-André Bombeck 63e8630fcb perf(bench): profile a production boot and the idle heap
scripts/bench/boot-profile.ts starts the production build with every role
under the production heap ceiling against the seeded benchmark database,
and records the time to a healthy probe and to a ready worker, every
event-loop stall the process logs, the heap lines, the full collections
from --trace-gc, the main thread's busy stretches during the boot with
their self time by source module (resolved through the chunk source maps),
and one heap snapshot after an idle wait, summarised by node type,
constructor, largest strings and largest retained subtrees.

The baseline on the current runtime: a 753 ms busy stretch at 0.7 s, most
of it the worker graph, and a live heap of 164 to 172 MB after five idle
minutes, of which the query compiler holds about 50 MB and the eight
locale catalogs about 33 MB (32 parsed copies and two 9.7 MB chunk
sources).
2026-10-22 06:41:15 +02:00

8.6 KiB

Boot profile v1.45.0-before-boot

Commit 0f6d668df, 2026-10-22T04:36:55.826Z. Production build, every role, heap ceiling 792 MB, 300 s idle. 14 cores, load average 9.3,9.4,11.2 at the end.

  • first answer from /api/health: 1590 ms; background role ready: 5432 ms
  • event-loop stalls logged: 0, max 0 ms

Stalls

Heap samples

at s used MB old large obj code external array buffers rss
6 184 105 68 4 11 0 267
308 164 99 58 5 11 0 623

Full collections (mark-compact)

47 mark-compacts during the run. Used heap before the collection, and what survived it (the live heap):

at s before MB after MB
0 21.4 17.4
9 189.6 172.9
154 193.8 171.6
170 187.3 161.7
188 181.6 163.6
205 182.3 163.6
222 190.6 165
239 182.9 163.4
258 190.5 163.7
274 187.7 164.2
290 193.9 164.2
306 175.3 163.9
309 174 163.7

Main-thread busy stretches over 50 ms without an idle sample, first two minutes

at 5 ms, 279 ms

self time by module ms
(native) 122.3
npm:next 57.1
node:internal/modules/cjs/loader 41.7
node:internal/bootstrap/realm 24.7
node:fs 5.3
node:internal/deps/undici/undici 5.3
node:internal/modules/package_json_reader 4.5
node:path 4
node:internal/streams/destroy 1.5
node:internal/deps/cjs-module-lexer/lexer 1.5
inclusive, application modules ms

at 339 ms, 324 ms

self time by module ms
(native) 87.6
node:internal/modules/cjs/loader 54.2
npm:@prisma/client 38
wasm://wasm/00d1cb12 36
node:internal/modules/esm/utils 26.7
turbopack:///[turbopack]/nodejs/runtime/build-base.ts 24.9
npm:next 22.1
npm:zod 6
turbopack:///[turbopack]/shared/runtime/runtime-utils.ts 3.1
npm:@prisma/client-runtime-utils 3
inclusive, application modules ms
src/instrumentation.ts 80.6
src/lib/db-session.ts 60.7
src/lib/notifications/types.ts 13.2
src/lib/boot/readiness-summary.ts 13.2
src/lib/ai/local-host-allowlist.ts 13.2
src/generated/prisma/internal/class.ts 7.3
src/lib/logging/context.ts 6
src/lib/crypto.ts 6
src/lib/boot/key-check.ts 6
src/lib/validations/measurement.ts 3

at 698 ms, 753 ms

self time by module ms
node:internal/modules/cjs/loader 178.2
turbopack:///[turbopack]/nodejs/runtime/build-base.ts 177.4
(native) 83.8
npm:zod 39.5
npm:next 34.6
turbopack:///[turbopack]/shared/runtime/async-module.ts 33.9
npm:mmdb-lib 26.1
node:fs 23.5
npm:yaml 22.4
src/lib/activity/goal-bounds.ts 18.5
inclusive, application modules ms
src/instrumentation.ts 410
src/lib/jobs/reminder/register-maintenance.ts 279.5
src/lib/sharing/acting-session.ts 138.5
src/lib/jobs/offhost-backup.ts 137.1
src/lib/integrations/oauth-refresh.ts 136.3
src/lib/jobs/morning-digest-refresh-shared.ts 136.3
src/lib/export/environment-backup.ts 134.1
src/lib/export/full-backup-payload.ts 134.1
src/app/api/health/route.ts 127.5
src/lib/insights/snapshot-hash.ts 124.9

Self time by module until the worker is ready

module ms
(native) 524.6
node:internal/modules/cjs/loader 274
turbopack:///[turbopack]/nodejs/runtime/build-base.ts 202.3
npm:next 136.8
wasm://wasm/00d1cb12 108.1
npm:@prisma/client 76.1
npm:pg 56.5
npm:zod 45.5
node:internal/modules/esm/utils 41.4
npm:luxon 38.5
turbopack:///[turbopack]/shared/runtime/async-module.ts 35.3
node:fs 31.7
node:internal/bootstrap/realm 28.9
npm:pg-protocol 27.7
npm:mmdb-lib 26.1
npm:yaml 22.4
npm:pg-boss 19.3
src/lib/activity/goal-bounds.ts 18.5
node:internal/process/task_queues 17.7
node:internal/streams/readable 15.5
node:internal/async_hooks 15.1
npm:cron-parser 14.6
node:internal/timers 12.8
turbopack:///[turbopack]/shared/runtime/runtime-utils.ts 12.4
node:buffer 11.6

Heap snapshot after 300 s idle (live heap after a full GC)

172.3 MB in 1412114 nodes; module source strings over 50 KB: 44.2 MB.

  • parsed locale catalogs: 32 objects, 14.1 MB retained
node type MB
string 79.1
array 27.6
code 18.6
object 16.7
hidden 9.3
native 8
object shape 5.8
closure 5
concatenated string 1.3
number 0.4
regexp 0.2
sliced string 0.2
synthetic 0
symbol 0
bigint 0
constructor MB count
array:(object elements) 20.6 24726
object:Object 11.9 300844
native:system / JSArrayBufferData 7.5 169
array:(object properties) 4.4 6540
array: 2.7 9578
object:system / Context 1.6 28887
closure: 1.5 27081
object:Date1 1 10632
closure:native_bind 0.9 20134
object:Array 0.6 19550
object:a 0.4 3880
native:Node / histogram 0.4 1
closure:get 0.3 4717
object:Set 0.2 5102
closure:set 0.2 3414
object:d 0.2 3874
object:Module 0.1 1907
object:Promise 0.1 1590
closure:n 0.1 1400
closure:i 0.1 1390
largest retained subtrees MB retaining path
object:yr 33.9 [1] > [10] > 15 > extension > global > prisma > [1] > _engine
object:Object 10 tX > onClose > onClose > context > system / Context > previous > system / Context > e > Context > proto > c
code:.next/server/chu 9.8 system / Context > timerListMap > Object > [120000] > TimersList > _idleNext > Timeout > _onTimeout > > shared > script
code:.next/server/chu 9.7 Module > cache > Object > .next/server/chunks/09yxiz..js > Module > exports > Array > [1] > > shared > script
object:system / Context 7.4 Node / PrincipalRealm > base_object_list > Node / BaseObjectList > [25] > Node / ModuleWrap > native_to_javascript > ModuleWrap > 2 > [4] > context
code:.next/server/chu 5.6 global > prisma > [1] > t > _engineConfig > Object > compilerWasm > Object > getRuntime > getRuntime > shared > script
code:.next/server/chu 5.6 Module > _cache > Object > .next/server/chunks/0hfea7u..js > Module > exports > Array > [1] > > shared > script
object:Generator 4.4 [6] > principal_realm > Node / PrincipalRealm > base_object_list > Node / BaseObjectList > [26] > Node / ModuleWrap > native_to_javascript > ModuleWrap > 2 > [4
string:AGFzbQEAAAABtgRLYAN/f38Bf2ACf38Bf2ACf38AYAF/AGADf39/AGAEf39/ 4.4 [1] > [21] > 59867
code:.next/server/chu 3.7 [1] > [10] > 15 > extension > global > healthlog_pgboss > PgBoss > _events > Object > error > > shared > script
object:Client 3.6 Object > close > > context > system / Context > self > Connection > _events > Object > parseComplete > bound_this
largest strings MB
module.exports=[425781,(e,a,i)=>{a.exports=JSON.parse('{"common":{"listCapped":"Hier stehe 9.7
module.exports=[157893,(e,a,i)=>{a.exports=JSON.parse('{"common":{"listCapped":"Hier stehe 9.7
module.exports=[17856,A=>{"use strict";var e,C,g,I,Q=Object.defineProperty,B={},s={$:()=>i 5.6
module.exports=[234494,A=>{"use strict";var e,C,g,I,Q=Object.defineProperty,B={},s={$:()=> 5.6
const wasm = "AGFzbQEAAAABtgRLYAN/f38Bf2ACf38Bf2ACf38AYAF/AGADf39/AGAEf39/fwBgBX9/f39/AGAB 4.4
AGFzbQEAAAABtgRLYAN/f38Bf2ACf38Bf2ACf38AYAF/AGADf39/AGAEf39/fwBgBX9/f39/AGABfwF/YAZ/f39/f3 4.4
module.exports=[799092,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value: 3.7
lliADOAUngIEAACgKwAgBgAAoSsAIAcAAKErACAIAACiKwAgCQAAoysAIAoAAKQrACALAAClKwAgDAAApisAIA0AAK 1.9
(()=>{var e,t,r={"./dist/build/webpack/alias/react-dom-server.js"(e,t,r){"use strict";var 1.3
module.exports=[842865,(e,t,r)=>{let i=e.r(522734);t.exports=function(e){return e?/-----BE 1.2
module.exports=[834886,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value: 1.1
// v1.4.34 web-freeze. Schema is locked additive-only until iOS launch // + v1.5.0 marker. 1.1
module.exports=[971743,(A,e,t)=>{"use strict";let r=A.r(57328),{addAbortListener:s}=A.r(68 1.1
module.exports=[835717,(A,e,t)=>{"use strict";let r=A.r(57328),{addAbortListener:s}=A.r(68 1
module.exports=[594108,806176,674750,98746,t=>{"use strict";var i;let r;function n(t){retu 0.7