@typeberry/lib 0.6.1 → 0.6.2-4b14e8e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -60,7 +60,6 @@
60
60
  * └── workers/
61
61
  * ```
62
62
  */
63
- import { execSync } from "node:child_process";
64
63
  import fs from "node:fs";
65
64
  import path from "node:path";
66
65
  import { fileURLToPath } from "node:url";
@@ -71,26 +70,26 @@ const DIST_DIR = path.resolve(ROOT_DIR, "dist/lib");
71
70
  /**
72
71
  * Get the version string for the package
73
72
  *
74
- * If IS_RELEASE environment variable is set, uses the version from package.json as-is.
75
- * Otherwise, appends the current git commit hash to create unique versions for each build.
73
+ * If the VERSION_SHA environment variable is set (e.g. CI builds), appends it to
74
+ * the base version to create a unique, non-release version. Otherwise (release
75
+ * behavior) the base version from package.json is used as-is.
76
76
  *
77
77
  * @param baseVersion - The base version from package.json
78
78
  * @returns The version string to use for publishing
79
79
  *
80
80
  * @example
81
- * // When IS_RELEASE is not set and commit is abc1234
81
+ * // When VERSION_SHA=abc1234
82
82
  * getVersion("0.5.1") // Returns "0.5.1-abc1234"
83
83
  *
84
- * // When IS_RELEASE is set
84
+ * // When VERSION_SHA is not set
85
85
  * getVersion("0.5.1") // Returns "0.5.1"
86
86
  */
87
87
  function getVersion(baseVersion) {
88
- const isRelease = Boolean(process.env.IS_RELEASE);
89
- if (isRelease) {
88
+ const versionSha = process.env.VERSION_SHA;
89
+ if (versionSha === undefined || versionSha === "") {
90
90
  return baseVersion;
91
91
  }
92
- const commitHash = execSync("git rev-parse --short HEAD").toString("utf8").trim();
93
- return `${baseVersion}-${commitHash}`;
92
+ return `${baseVersion}-${versionSha}`;
94
93
  }
95
94
  /**
96
95
  * Build a map of package names to their workspace paths
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typeberry/lib",
3
- "version": "0.6.1",
3
+ "version": "0.6.2-4b14e8e",
4
4
  "description": "Typeberry Library",
5
5
  "main": "./bin/lib/index.js",
6
6
  "types": "./bin/lib/index.d.ts",
@@ -264,7 +264,7 @@
264
264
  "#@typeberry/jam-network/*": "./packages/workers/jam-network/*"
265
265
  },
266
266
  "dependencies": {
267
- "@fluffylabs/anan-as": "^1.3.0",
267
+ "@fluffylabs/anan-as": "^1.4.0",
268
268
  "@noble/ed25519": "2.2.3",
269
269
  "hash-wasm": "4.12.0",
270
270
  "@typeberry/native": "0.2.0-74dd7d7",
@@ -10,12 +10,15 @@ export type ExecutorOptions = {
10
10
  * when there is too many tasks pending in the queue.
11
11
  */
12
12
  maxWorkers: number;
13
+ /** Worker heap size limit (defaults to 2048 MB) */
14
+ maxHeapSize?: number;
13
15
  };
14
16
  /** Execution pool manager. */
15
17
  export declare class Executor<TParams extends WithTransferList, TResult> implements IExecutor<TParams, TResult> {
16
18
  private readonly workers;
17
19
  private readonly maxWorkers;
18
20
  private readonly workerPath;
21
+ private readonly maxHeapSize?;
19
22
  /** Initialize a new concurrent executor given a path to the worker. */
20
23
  static initialize<XParams extends WithTransferList, XResult extends WithTransferList>(workerPath: URL, options: ExecutorOptions): Promise<Executor<XParams, XResult>>;
21
24
  private readonly freeWorkerIndices;
@@ -1 +1 @@
1
- {"version":3,"file":"parent.d.ts","sourceRoot":"","sources":["../../../../../packages/core/concurrent/parent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAyB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAMxF,wBAAwB;AACxB,MAAM,MAAM,eAAe,GAAG;IAC5B,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,8BAA8B;AAC9B,qBAAa,QAAQ,CAAC,OAAO,SAAS,gBAAgB,EAAE,OAAO,CAAE,YAAW,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAsBnG,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAvB7B,uEAAuE;WAC1D,UAAU,CAAC,OAAO,SAAS,gBAAgB,EAAE,OAAO,SAAS,gBAAgB,EACxF,UAAU,EAAE,GAAG,EACf,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAWtC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,oBAAoB,CAAS;IAErC,OAAO;IAWP,0CAA0C;IACpC,aAAa,CAAC,SAAS,GAAE,MAAM,IAAe;IAiBpD,oDAAoD;IAC9C,OAAO;IASb,4CAA4C;IACtC,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB5C,kDAAkD;IAClD,OAAO,CAAC,yBAAyB;CA6BlC"}
1
+ {"version":3,"file":"parent.d.ts","sourceRoot":"","sources":["../../../../../packages/core/concurrent/parent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAyB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAOxF,wBAAwB;AACxB,MAAM,MAAM,eAAe,GAAG;IAC5B,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,8BAA8B;AAC9B,qBAAa,QAAQ,CAAC,OAAO,SAAS,gBAAgB,EAAE,OAAO,CAAE,YAAW,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAsBnG,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAxB/B,uEAAuE;WAC1D,UAAU,CAAC,OAAO,SAAS,gBAAgB,EAAE,OAAO,SAAS,gBAAgB,EACxF,UAAU,EAAE,GAAG,EACf,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAWtC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,oBAAoB,CAAS;IAErC,OAAO;IAYP,0CAA0C;IACpC,aAAa,CAAC,SAAS,GAAE,MAAM,IAAe;IAiBpD,oDAAoD;IAC9C,OAAO;IASb,4CAA4C;IACtC,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB5C,kDAAkD;IAClD,OAAO,CAAC,yBAAyB;CA6BlC"}
@@ -3,30 +3,33 @@ import { check } from "#@typeberry/utils";
3
3
  // Amount of tasks in the queue that will trigger creation of new worker thread.
4
4
  // NOTE this might need to be configurable in the future.
5
5
  const QUEUE_SIZE_WORKER_THRESHOLD = 5;
6
+ const DEFAULT_MAX_HEAP_SIZE_MB = 2048;
6
7
  /** Execution pool manager. */
7
8
  export class Executor {
8
9
  workers;
9
10
  maxWorkers;
10
11
  workerPath;
12
+ maxHeapSize;
11
13
  /** Initialize a new concurrent executor given a path to the worker. */
12
14
  static async initialize(workerPath, options) {
13
15
  check `${options.maxWorkers > 0} Max workers has to be positive.`;
14
16
  check `${options.minWorkers <= options.maxWorkers} Min workers must be less than or equal to max workers (min=${options.minWorkers}, max=${options.maxWorkers}).`;
15
17
  const workers = [];
16
18
  for (let i = 0; i < options.minWorkers; i++) {
17
- workers.push(await initWorker(workerPath));
19
+ workers.push(await initWorker(workerPath, options.maxHeapSize));
18
20
  }
19
- return new Executor(workers, options.maxWorkers, workerPath);
21
+ return new Executor(workers, options.maxWorkers, workerPath, options.maxHeapSize);
20
22
  }
21
23
  // keeps track of the indices of worker threads that are currently free and available to execute tasks
22
24
  freeWorkerIndices = [];
23
25
  taskQueue = [];
24
26
  isDestroyed = false;
25
27
  isWorkerInitializing = false;
26
- constructor(workers, maxWorkers, workerPath) {
28
+ constructor(workers, maxWorkers, workerPath, maxHeapSize) {
27
29
  this.workers = workers;
28
30
  this.maxWorkers = maxWorkers;
29
31
  this.workerPath = workerPath;
32
+ this.maxHeapSize = maxHeapSize;
30
33
  // intial free workers.
31
34
  for (let i = 0; i < workers.length; i++) {
32
35
  this.freeWorkerIndices.push(i);
@@ -43,7 +46,7 @@ export class Executor {
43
46
  return;
44
47
  }
45
48
  this.isWorkerInitializing = true;
46
- this.workers.push(await initWorker(this.workerPath));
49
+ this.workers.push(await initWorker(this.workerPath, this.maxHeapSize));
47
50
  this.freeWorkerIndices.push(this.workers.length - 1);
48
51
  this.isWorkerInitializing = false;
49
52
  onSuccess();
@@ -101,10 +104,10 @@ export class Executor {
101
104
  });
102
105
  }
103
106
  }
104
- async function initWorker(workerPath) {
107
+ async function initWorker(workerPath, maxOldGenerationSizeMb = DEFAULT_MAX_HEAP_SIZE_MB) {
105
108
  // create a worker and initialize communication channel
106
109
  const { port1, port2 } = new MessageChannel();
107
- const workerThread = new Worker(workerPath, {});
110
+ const workerThread = new Worker(workerPath, { resourceLimits: { maxOldGenerationSizeMb } });
108
111
  workerThread.postMessage(port1, [port1]);
109
112
  // // wait for the worker to start
110
113
  await new Promise((resolve, reject) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/core/pvm-interpreter-ananas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAY,KAAK,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,KAAK,GAAG,EAER,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,KAAK,UAAU,EAEf,KAAK,SAAS,EAEd,MAAM,EAGP,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAS,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAErD,KAAK,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC;AAKtD,cAAM,eAAgB,YAAW,UAAU;IAKrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ7C,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO;IAEP,aAAa,IAAI,UAAU;IAI3B,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAOtC,SAAS,IAAI,cAAc;CAI5B;AAED,cAAM,YAAa,YAAW,OAAO;IAKf,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ7C,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO;IAEP,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC;IAO7D,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC;CAW9D;AAED,cAAM,gBAAiB,YAAW,WAAW;IAOvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAN7C,UAAU,EAAE,GAAG,CAAgB;IAE/B,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO;IAEP,GAAG,IAAI,GAAG;IAIV,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI;IAIjB,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO;IAUpB,IAAI,IAAI,GAAG;CASZ;AAED,qBAAa,iBAAkB,YAAW,eAAe;IAKnC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ7C,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAE/B,OAAO;WAMM,GAAG;IAWhB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI;IAO3E,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI;IAS9D,QAAQ,IAAI,OAAO;IAInB,UAAU,IAAI,IAAI;IAMlB,SAAS,IAAI,MAAM;IASnB,KAAK,IAAI,MAAM;IAIf,YAAY,IAAI,GAAG,GAAG,IAAI;CAG3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/core/pvm-interpreter-ananas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAY,KAAK,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,KAAK,GAAG,EAER,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,KAAK,UAAU,EAEf,KAAK,SAAS,EAEd,MAAM,EAGP,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAS,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAErD,KAAK,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC;AAKtD,cAAM,eAAgB,YAAW,UAAU;IAKrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ7C,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO;IAEP,aAAa,IAAI,UAAU;IAI3B,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAOtC,SAAS,IAAI,cAAc;CAI5B;AAED,cAAM,YAAa,YAAW,OAAO;IAKf,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ7C,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO;IAEP,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC;IAO7D,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC;CAW9D;AAED,cAAM,gBAAiB,YAAW,WAAW;IAOvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAN7C,UAAU,EAAE,GAAG,CAAgB;IAE/B,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO;IAEP,GAAG,IAAI,GAAG;IAIV,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI;IAIjB,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO;IAUpB,IAAI,IAAI,GAAG;CASZ;AAKD,qBAAa,iBAAkB,YAAW,eAAe;IAKnC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ7C,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAE/B,OAAO;WAMM,GAAG;IAWhB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI;IAO3E,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI;IAkB9D,QAAQ,IAAI,OAAO;IAInB,UAAU,IAAI,IAAI;IAMlB,SAAS,IAAI,MAAM;IASnB,KAAK,IAAI,MAAM;IAIf,YAAY,IAAI,GAAG,GAAG,IAAI;CAG3B"}
@@ -84,6 +84,8 @@ class AnanasGasCounter {
84
84
  return tryAsBigGas(gasConsumed);
85
85
  }
86
86
  }
87
+ const USE_BLOCK_GAS = false;
88
+ const PAGES_TO_PREALLOCATE = 192;
87
89
  export class AnanasInterpreter {
88
90
  instance;
89
91
  registers;
@@ -109,7 +111,7 @@ export class AnanasInterpreter {
109
111
  const programArr = lowerBytes(program);
110
112
  const argsArr = lowerBytes(args);
111
113
  this.gas.initialGas = gas;
112
- this.instance.resetJAM(programArr, pc, BigInt(gas), argsArr, true, false);
114
+ this.instance.resetJAM(programArr, pc, BigInt(gas), argsArr, true, USE_BLOCK_GAS, PAGES_TO_PREALLOCATE);
113
115
  }
114
116
  resetGeneric(program, _pc, gas) {
115
117
  const programArr = lowerBytes(program);
@@ -117,7 +119,7 @@ export class AnanasInterpreter {
117
119
  const pageMap = new Uint8Array();
118
120
  const chunks = new Uint8Array();
119
121
  this.gas.initialGas = gas;
120
- this.instance.resetGenericWithMemory(programArr, emptyRegisters, pageMap, chunks, BigInt(gas), false);
122
+ this.instance.resetGenericWithMemory(programArr, emptyRegisters, pageMap, chunks, BigInt(gas), false, USE_BLOCK_GAS, PAGES_TO_PREALLOCATE);
121
123
  }
122
124
  nextStep() {
123
125
  return this.instance.nextStep();
@@ -16,4 +16,17 @@ export declare function logHostEnvironment(logger: Logger): void;
16
16
  * already logged by `logHostEnvironment` on the main thread.
17
17
  */
18
18
  export declare function logHeapLimit(logger: Logger, workerName: string): void;
19
+ /**
20
+ * `resourceLimits` to pass to `new Worker(...)` so the worker isolate gets the
21
+ * same heap budget as the main thread.
22
+ *
23
+ * Worker threads run in their own V8 isolate and do not reliably inherit the
24
+ * main thread's `--max-old-space-size` (set via NODE_OPTIONS). Without this they
25
+ * fall back to V8's default (~2 GiB) and abort with SIGABRT (exit code 134) once
26
+ * they outgrow it. Call this on the main thread at spawn time so we propagate
27
+ * whatever limit the process was actually started with.
28
+ */
29
+ export declare function workerResourceLimits(): {
30
+ maxOldGenerationSizeMb: number;
31
+ };
19
32
  //# sourceMappingURL=host-environment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-environment.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/host-environment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIhD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAoBvD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAErE"}
1
+ {"version":3,"file":"host-environment.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/host-environment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIhD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAoBvD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAErE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI;IAAE,sBAAsB,EAAE,MAAM,CAAA;CAAE,CAIzE"}
@@ -39,6 +39,21 @@ export function logHostEnvironment(logger) {
39
39
  export function logHeapLimit(logger, workerName) {
40
40
  logger.info `📦 V8 heap limit (${workerName}): ${toGiB(v8.getHeapStatistics().heap_size_limit)}.`;
41
41
  }
42
+ /**
43
+ * `resourceLimits` to pass to `new Worker(...)` so the worker isolate gets the
44
+ * same heap budget as the main thread.
45
+ *
46
+ * Worker threads run in their own V8 isolate and do not reliably inherit the
47
+ * main thread's `--max-old-space-size` (set via NODE_OPTIONS). Without this they
48
+ * fall back to V8's default (~2 GiB) and abort with SIGABRT (exit code 134) once
49
+ * they outgrow it. Call this on the main thread at spawn time so we propagate
50
+ * whatever limit the process was actually started with.
51
+ */
52
+ export function workerResourceLimits() {
53
+ return {
54
+ maxOldGenerationSizeMb: Math.floor(v8.getHeapStatistics().heap_size_limit / 1024 ** 2),
55
+ };
56
+ }
42
57
  /** Read the cgroup (v2, then v1) memory limit in bytes, or null if unlimited / unavailable. */
43
58
  function readCgroupMemoryLimit() {
44
59
  if (os.platform() !== "linux") {
@@ -4,7 +4,7 @@ import { Level, Logger } from "#@typeberry/logger";
4
4
  import { assertNever } from "#@typeberry/utils";
5
5
  import { Channel } from "#@typeberry/workers-api";
6
6
  import { configTransferList, LmdbWorkerConfig } from "./config.js";
7
- import { logHeapLimit } from "./host-environment.js";
7
+ import { logHeapLimit, workerResourceLimits } from "./host-environment.js";
8
8
  import { ThreadPort } from "./port.js";
9
9
  const logger = Logger.new(import.meta.filename, "workers");
10
10
  /** Type of the control plane message. */
@@ -31,7 +31,7 @@ function isControlPlane(data) {
31
31
  export function spawnWorker(protocol, bootstrapPath, config, paramsEncoder) {
32
32
  logger.trace `Spawning ${protocol.name} child worker.`;
33
33
  const channel = new MessageChannel();
34
- const worker = new Worker(bootstrapPath);
34
+ const worker = new Worker(bootstrapPath, { resourceLimits: workerResourceLimits() });
35
35
  const msg = {
36
36
  kind: WorkerControlPlaneMsg.Config,
37
37
  parentPort: channel.port2,