Skip to content

Commit 3a2bcd7

Browse files
feat: allow setting rust min stack size
Signed-off-by: Victor Adossi <vadossi@cosmonic.com>
1 parent 7f17009 commit 3a2bcd7

File tree

2 files changed

+62
-12
lines changed

2 files changed

+62
-12
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ The component iself can be executed in any component runtime, see the [example](
111111

112112
To enable AOT compilation, set the `enableAot: true` option to run [Weval][weval] ahead-of-time compilation.
113113

114+
AOT compilation can also be configured with the following options:
115+
116+
| Option | Type | Example | Description |
117+
|------------------------|-------------------------------------|-----------------|--------------------------------------------------------------------------|
118+
| `aotMinStackSizeBytes` | `nubmer | Number | bigint | BigInt` | `2_007_846_092` | The minimum stack size (via `RUST_MIN_STACK` to set when running `weval` |
119+
114120
[weval]: https://github.com/bytecodealliance/weval
115121

116122
### Custom `weval` binary

src/componentize.js

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { freemem } from "node:os";
12
import wizer from '@bytecodealliance/wizer';
23
import getWeval from '@bytecodealliance/weval';
34
import {
@@ -18,7 +19,7 @@ import {
1819
import { fileURLToPath } from 'node:url';
1920
import { cwd, stdout, platform } from 'node:process';
2021
export const { version } = JSON.parse(
21-
await readFile(new URL('../package.json', import.meta.url), 'utf8')
22+
await readFile(new URL('../package.json', import.meta.url), 'utf8'),
2223
);
2324
const isWindows = platform === 'win32';
2425

@@ -56,6 +57,24 @@ function parseWizerStderr(stderr) {
5657
return `${output.substring(0, causeStart)}${output.substring(causeEnd)}`.trim();
5758
}
5859

60+
/**
61+
* Check whether a value is numeric (including BigInt)
62+
*
63+
* @param {any} n
64+
* @returns {boolean} whether the value is numeric
65+
*/
66+
function isNumeric(n) {
67+
switch (typeof n) {
68+
case 'bigint':
69+
case 'number':
70+
return true;
71+
case 'object':
72+
return n.constructor == BigInt || n.constructor == Number;
73+
default:
74+
return false;
75+
}
76+
}
77+
5978
export async function componentize(opts,
6079
_deprecatedWitWorldOrOpts = undefined,
6180
_deprecatedOpts = undefined) {
@@ -106,7 +125,7 @@ export async function componentize(opts,
106125
debugBindings = false,
107126
enableWizerLogging = false,
108127
aotCache = fileURLToPath(
109-
new URL(`../lib/starlingmonkey_ics.wevalcache`, import.meta.url)
128+
new URL(`../lib/starlingmonkey_ics.wevalcache`, import.meta.url),
110129
),
111130
} = opts;
112131

@@ -116,11 +135,9 @@ export async function componentize(opts,
116135
new URL(
117136
opts.enableAot
118137
? `../lib/starlingmonkey_embedding_weval.wasm`
119-
: `../lib/starlingmonkey_embedding${
120-
debugBuild ? '.debug' : ''
121-
}.wasm`,
122-
import.meta.url
123-
)
138+
: `../lib/starlingmonkey_embedding${debugBuild ? '.debug' : ''}.wasm`,
139+
import.meta.url,
140+
),
124141
);
125142

126143
let { wasm, jsBindings, exports, imports } = spliceBindings(
@@ -229,6 +246,10 @@ export async function componentize(opts,
229246
}
230247

231248
let wizerProcess;
249+
// let sourcePath = maybeWindowsPath(
250+
// join(sourceDir, sourceName.slice(0, -3) + '.bindings.js'),
251+
// );
252+
// runtimeArgs = runtimeArgs ? `${runtimeArgs} ${sourcePath}` : sourcePath;
232253

233254
if (opts.enableAot) {
234255
// Determine the weval bin path, possibly using a pre-downloaded version
@@ -239,6 +260,18 @@ export async function componentize(opts,
239260
wevalBin = await getWeval();
240261
}
241262

263+
// Set the min stack size, if one was provided
264+
if (opts.aotMinStackSizeBytes) {
265+
if (!isNumeric(opts.aotMinStackSizeBytes)) {
266+
throw new TypeError(
267+
`aotMinStackSizeBytes must be a numeric value, received [${opts.aotMinStackSizeBytes}] (type ${typeof opts.aotMinStackSizeBytes})`,
268+
);
269+
}
270+
env.RUST_MIN_STACK = opts.aotMinStackSizeBytes;
271+
} else {
272+
env.RUST_MIN_STACK = defaultMinStackSize();
273+
}
274+
242275
wizerProcess = spawnSync(
243276
wevalBin,
244277
[
@@ -312,7 +345,7 @@ export async function componentize(opts,
312345
async function initWasm(bin) {
313346
const eep = (name) => () => {
314347
throw new Error(
315-
`Internal error: unexpected call to "${name}" during Wasm verification`
348+
`Internal error: unexpected call to "${name}" during Wasm verification`,
316349
);
317350
};
318351

@@ -332,7 +365,7 @@ export async function componentize(opts,
332365
const bufPtr = mem.getUint32(iovs + i * 8, true);
333366
const bufLen = mem.getUint32(iovs + 4 + i * 8, true);
334367
stderr += new TextDecoder().decode(
335-
new Uint8Array(exports.memory.buffer, bufPtr, bufLen)
368+
new Uint8Array(exports.memory.buffer, bufPtr, bufLen),
336369
);
337370
written += bufLen;
338371
}
@@ -390,7 +423,7 @@ export async function componentize(opts,
390423
features,
391424
witWorld,
392425
maybeWindowsPath(witPath),
393-
worldName
426+
worldName,
394427
);
395428

396429
if (debugBindings) {
@@ -403,12 +436,12 @@ export async function componentize(opts,
403436
Object.entries({
404437
wasi_snapshot_preview1: await readFile(preview2Adapter),
405438
}),
406-
false
439+
false,
407440
),
408441
Object.entries({
409442
language: [['JavaScript', '']],
410443
'processed-by': [['ComponentizeJS', version]],
411-
})
444+
}),
412445
);
413446

414447
// convert CABI import conventions to ESM import conventions
@@ -421,3 +454,14 @@ export async function componentize(opts,
421454
imports,
422455
};
423456
}
457+
458+
/**
459+
* Calculate the min stack size depending on free memory
460+
*
461+
* @param {number} freeMemoryBytes - Amount of free memory in the system, in bytes (if not provided, os.freemem() is used)
462+
* @returns {number} The minimum stack size that should be used as a default.
463+
*/
464+
function defaultMinStackSize(freeMemoryBytes) {
465+
freeMemoryBytes = freeMemoryBytes ?? freemem();
466+
return Math.max(8 * 1024 * 1024, Math.floor(freeMemoryBytes * 0.1));
467+
}

0 commit comments

Comments
 (0)