@insanitybit/bun-prewarm 0.0.1
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.
- package/README.md +34 -0
- package/bin/bun-prewarm.js +93 -0
- package/package.json +16 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# bun-prewarm
|
|
2
|
+
|
|
3
|
+
Prewarm Bun runtime state inside a Firecracker VM before snapshotting.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
This package warms Bun-related filesystem, binary, and runtime state so that after snapshot restore, Bun startup and first-execution latency are lower.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install -g @insanitybit/bun-prewarm
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
Run explicitly during VM snapshot build:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
bun-prewarm
|
|
21
|
+
# then snapshot the VM
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## What it does
|
|
25
|
+
|
|
26
|
+
1. Runs `bun --version` to fault the Bun binary into memory
|
|
27
|
+
2. Executes a small JS workload under Bun to warm parsing and runtime
|
|
28
|
+
3. Runs `bun install --no-save` to warm package manager code paths
|
|
29
|
+
|
|
30
|
+
## Requirements
|
|
31
|
+
|
|
32
|
+
- Bun must be installed and available on `$PATH`
|
|
33
|
+
- Linux environment (Firecracker VM)
|
|
34
|
+
- Node.js 18+ (for running the prewarm script itself)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execSync } = require("child_process");
|
|
4
|
+
const { mkdtempSync, writeFileSync } = require("fs");
|
|
5
|
+
const { tmpdir } = require("os");
|
|
6
|
+
const { join } = require("path");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Prewarm Bun runtime state for Firecracker VM snapshotting.
|
|
10
|
+
*
|
|
11
|
+
* Steps:
|
|
12
|
+
* 1. Run `bun --version` to fault the binary into memory
|
|
13
|
+
* 2. Execute a small JS workload under Bun
|
|
14
|
+
* 3. Run `bun install --no-save` to warm install code paths
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
function log(message) {
|
|
18
|
+
console.log(`[bun-prewarm] ${message}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function run(command, options = {}) {
|
|
22
|
+
log(`Running: ${command}`);
|
|
23
|
+
try {
|
|
24
|
+
const output = execSync(command, {
|
|
25
|
+
encoding: "utf8",
|
|
26
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
27
|
+
...options,
|
|
28
|
+
});
|
|
29
|
+
return output.trim();
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error(`[bun-prewarm] Command failed: ${command}`);
|
|
32
|
+
console.error(`[bun-prewarm] Exit code: ${error.status}`);
|
|
33
|
+
if (error.stderr) {
|
|
34
|
+
console.error(`[bun-prewarm] stderr: ${error.stderr}`);
|
|
35
|
+
}
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Step 1: Fault Bun binary and runtime
|
|
41
|
+
log("Step 1: Faulting Bun binary into memory");
|
|
42
|
+
const bunVersion = run("bun --version");
|
|
43
|
+
log(`Bun version: ${bunVersion}`);
|
|
44
|
+
|
|
45
|
+
// Step 2: Execute a small JS program under Bun
|
|
46
|
+
log("Step 2: Executing JS workload under Bun");
|
|
47
|
+
|
|
48
|
+
const tempDir = mkdtempSync(join(tmpdir(), "bun-prewarm-"));
|
|
49
|
+
log(`Created temp directory: ${tempDir}`);
|
|
50
|
+
|
|
51
|
+
// A simple workload that exercises parsing, runtime, and execution
|
|
52
|
+
const workloadScript = `
|
|
53
|
+
// Non-trivial loop to prevent total optimization removal
|
|
54
|
+
let sum = 0;
|
|
55
|
+
for (let i = 0; i < 100000; i++) {
|
|
56
|
+
sum += Math.sqrt(i) * Math.sin(i);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Touch some built-in modules
|
|
60
|
+
const crypto = require("crypto");
|
|
61
|
+
const hash = crypto.createHash("sha256").update("prewarm").digest("hex");
|
|
62
|
+
|
|
63
|
+
// Print results to prove execution
|
|
64
|
+
console.log("Workload result:", sum.toFixed(4));
|
|
65
|
+
console.log("Hash:", hash.slice(0, 16));
|
|
66
|
+
console.log("Bun prewarm workload completed");
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
const workloadPath = join(tempDir, "workload.js");
|
|
70
|
+
writeFileSync(workloadPath, workloadScript);
|
|
71
|
+
log(`Wrote workload script to: ${workloadPath}`);
|
|
72
|
+
|
|
73
|
+
const workloadOutput = run(`bun ${workloadPath}`);
|
|
74
|
+
log(`Workload output:\n${workloadOutput}`);
|
|
75
|
+
|
|
76
|
+
// Step 3: Warm Bun install code paths
|
|
77
|
+
log("Step 3: Warming Bun install code paths");
|
|
78
|
+
|
|
79
|
+
// Create a minimal package.json in the temp directory
|
|
80
|
+
const minimalPackageJson = JSON.stringify({ name: "prewarm-dummy", private: true }, null, 2);
|
|
81
|
+
writeFileSync(join(tempDir, "package.json"), minimalPackageJson);
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
run("bun install --no-save", { cwd: tempDir });
|
|
85
|
+
log("Bun install completed");
|
|
86
|
+
} catch {
|
|
87
|
+
// Failure in install step is non-fatal as per design doc
|
|
88
|
+
// (network may not be available, etc.)
|
|
89
|
+
log("Bun install step skipped or failed (non-fatal)");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Done
|
|
93
|
+
log("Prewarm complete");
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@insanitybit/bun-prewarm",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Prewarm Bun runtime state inside a Firecracker VM before snapshotting",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"private": false,
|
|
7
|
+
"bin": {
|
|
8
|
+
"bun-prewarm": "bin/bun-prewarm.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin"
|
|
12
|
+
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
}
|
|
16
|
+
}
|