perf: bound V8's young generation and unbundle server-only deps
Two further wins, both measured on a restored 28-widget board behind a real demo session (scripts/benchmarks/stress-restore.mts). --max-semi-space-size=4 in run.sh. --max-old-space-size only bounds the old generation; V8 also sizes the young generation generously (16 MB per semi-space) and that slack is pure resident memory. 4 MB cut idle anonymous memory 120.0 -> 97.2 MiB and peak 710.6 -> 560.2 MiB. It costs CPU, as any GC-space reduction does — 15.8 -> 17.1 CPU-seconds over the run, ~8% — with no board-load latency regression (median 594 -> 570 ms). Overridable via HOMARR_MAX_SEMI_SPACE_SIZE. serverExternalPackages for the remaining server-only dependencies. Bundling a package inlines its transitive graph into a chunk that is compiled at boot even when the code path never runs; leaving it external makes it a lazy require. Adding winston, drizzle-orm, ical.js, jszip, ldapts, node-unifi, @kubernetes/client-node and linkedom took idle to 90.3 MiB and board-loaded 209.6 -> 164.6 MiB, with slightly lower CPU (16.3s) and latency (549 ms). The trade-off is image size: 388 -> 401 MB, because those packages now ship in node_modules instead of being tree-shaken into chunks. Cumulative vs the merge-base: idle 141.7 -> 90.3 MiB (-36%), board loaded 257.8 -> 164.6 MiB (-36%), under load 392.7 -> 302.5 MiB (-23%). The harness now proves the session rather than inferring it: it asserts an anonymous request to the private board is denied, requires the Auth.js session cookie after sign-in, and reports whether it had to modify the restored data at all (now "none"). It also records cgroup CPU seconds and board-load latency, so a memory win bought with CPU cannot hide. pnpm test 144/144 files, 1795 tests; typecheck and lint clean.
This commit is contained in:
4 files changed
+134
-16
No files matched your search
@@ -30,8 +30,28 @@ const nextConfig: NextConfig = {
|
||||
typescript: { ignoreBuildErrors: true },
|
||||
/**
|
||||
* dockerode is required in the external server packages because of https://github.com/homarr-labs/homarr/issues/612
|
||||
*
|
||||
* Everything else here is a server-only dependency that is cheaper left as a
|
||||
* runtime require than inlined into the server bundle. Bundling pulls a package's
|
||||
* whole transitive graph into a chunk that is loaded and compiled at boot even
|
||||
* when the code path never runs — measurably so for the DB drivers: only
|
||||
* better-sqlite3 is ever used, yet inlining mysql2 and pg cost ~21 MiB of
|
||||
* resident memory at idle.
|
||||
*/
|
||||
serverExternalPackages: ["dockerode", "better-sqlite3", "mysql2", "pg"],
|
||||
serverExternalPackages: [
|
||||
"dockerode",
|
||||
"better-sqlite3",
|
||||
"mysql2",
|
||||
"pg",
|
||||
"winston",
|
||||
"drizzle-orm",
|
||||
"ical.js",
|
||||
"jszip",
|
||||
"ldapts",
|
||||
"node-unifi",
|
||||
"@kubernetes/client-node",
|
||||
"linkedom",
|
||||
],
|
||||
experimental: {
|
||||
optimizePackageImports: ["@mantine/core", "@mantine/hooks", "@tabler/icons-react"],
|
||||
turbopackFileSystemCacheForBuild: true,
|
||||
|
||||
Reference in new issue
Block a user