Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental: add ahead-of-time compilation via weval and PBL. #883

Merged
merged 11 commits into from
Aug 2, 2024
Merged
24 changes: 20 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
profile: [debug, release]
profile: [debug, release, weval]
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -416,11 +416,19 @@ jobs:
- name: Build
if: ${{ matrix.profile == 'debug' }}
run: npm run build:starlingmonkey:debug
- name: Build
if: ${{ matrix.profile == 'weval' }}
run: npm run build:starlingmonkey:weval
- uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: starling-${{ matrix.profile }}
path: starling${{ matrix.profile == 'debug' && '.debug.wasm' || '.wasm' }}
path: starling${{ matrix.profile == 'debug' && '.debug.wasm' || (matrix.profile == 'weval' && '-weval.wasm' || '.wasm') }}
- uses: actions/upload-artifact@v3
if: ${{ matrix.profile == 'weval' }}
with:
name: starling-${{ matrix.profile }}-ic-cache
path: starling-ics.wevalcache

starlingmonkey-run_wpt:
concurrency:
Expand Down Expand Up @@ -487,10 +495,12 @@ jobs:
strategy:
matrix:
platform: [viceroy, compute]
profile: [debug, release]
profile: [debug, release, weval]
exclude:
- platform: compute
profile: release
- platform: compute
profile: weval
needs: [starlingmonkey-build]
steps:
- name: Checkout fastly/js-compute-runtime
Expand Down Expand Up @@ -532,11 +542,17 @@ jobs:
uses: actions/download-artifact@v3
with:
name: starling-${{ matrix.profile }}
- name: Download Engine (AOT weval cache)
uses: actions/download-artifact@v3
if: ${{ matrix.profile == 'weval'}}
with:
name: starling-${{ matrix.profile }}-ic-cache

- run: yarn install --frozen-lockfile

- name: Yarn install
run: yarn && cd ./integration-tests/js-compute && yarn

- run: SUFFIX_STRING=${{matrix.profile}} node integration-tests/js-compute/test.js ${{ matrix.platform == 'viceroy' && '--local' || '' }} ${{ matrix.profile == 'debug' && '--debug-build' || '' }}
- run: SUFFIX_STRING=${{matrix.profile}} node integration-tests/js-compute/test.js ${{ matrix.platform == 'viceroy' && '--local' || '' }} ${{ matrix.profile == 'weval' && '--aot' || '' }} ${{ matrix.profile == 'debug' && '--debug-build' || '' }}
env:
FASTLY_API_TOKEN: ${{ secrets.FASTLY_API_TOKEN }}
2 changes: 2 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ jobs:

- run: yarn build:starlingmonkey

- run: yarn build:starlingmonkey:weval

- run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
Expand Down
8 changes: 7 additions & 1 deletion integration-tests/js-compute/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ let args = argv.slice(2);

const local = args.includes('--local');
const starlingmonkey = !args.includes('--disable-starlingmonkey');
const aot = args.includes("--aot");
const debugBuild = args.includes('--debug-build');
const filter = args.filter(arg => !arg.startsWith('--'));

Expand All @@ -59,7 +60,7 @@ zx.verbose = true;
const branchName = (await zx`git branch --show-current`).stdout.trim().replace(/[^a-zA-Z0-9_-]/g, '_')

const fixture = 'app';
const serviceName = `${fixture}--${branchName}${starlingmonkey ? '--sm' : ''}${process.env.SUFFIX_STRING || ''}`
const serviceName = `${fixture}--${branchName}${starlingmonkey ? '--sm' : ''}${aot ? '--aot' : ''}${process.env.SUFFIX_STRING || ''}`
let domain;
const fixturePath = join(__dirname, 'fixtures', fixture)
let localServer;
Expand All @@ -73,6 +74,11 @@ if (!starlingmonkey) {
buildArgs.splice(-1, null, '--disable-starlingmonkey')
config.scripts.build = buildArgs.join(' ')
}
if (aot) {
const buildArgs = config.scripts.build.split(' ');
buildArgs.splice(-1, null, '--enable-experimental-aot');
config.scripts.build = buildArgs.join(' ');
}
if (debugBuild) {
const buildArgs = config.scripts.build.split(' ')
buildArgs.splice(-1, null, '--debug-build')
Expand Down
6 changes: 5 additions & 1 deletion js-compute-runtime-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { addSdkMetadataField } from "./src/addSdkMetadataField.js";

const {
enablePBL,
enableAOT,
aotCache,
enableExperimentalHighResolutionTimeMethods,
enableExperimentalTopLevelAwait,
starlingMonkey,
Expand Down Expand Up @@ -38,7 +40,9 @@ if (version) {
enableExperimentalHighResolutionTimeMethods,
enablePBL,
enableExperimentalTopLevelAwait,
starlingMonkey
starlingMonkey,
enableAOT,
aotCache,
);
await addSdkMetadataField(output, enablePBL, starlingMonkey);
}
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
"types",
"js-compute-runtime-cli.js",
"starling.wasm",
"starling-weval.wasm",
"js-compute-runtime.wasm",
"starling-ics.wevalcache",
"src",
"index.d.ts",
"package.json",
Expand All @@ -37,6 +39,7 @@
"build:debug": "DEBUG=true make -j8 -C runtime/js-compute-runtime && cp runtime/js-compute-runtime/js-compute-runtime.wasm .",
"build:starlingmonkey": "./runtime/fastly/build-release.sh",
"build:starlingmonkey:debug": "./runtime/fastly/build-debug.sh",
"build:starlingmonkey:weval": "./runtime/fastly/build-release-weval.sh",
"build:starlingmonkey:debug:info": "./runtime/fastly/build-debug.sh --keep-debug-info",
"format-changelog": "node ci/format-changelog.js CHANGELOG.md"
},
Expand All @@ -54,6 +57,7 @@
"dependencies": {
"@bytecodealliance/jco": "^1.3.1",
"@bytecodealliance/wizer": "^3.0.1",
"@cfallin/weval": "^0.2.9",
"acorn": "^8.12.1",
"acorn-walk": "^8.3.3",
"esbuild": "^0.23.0",
Expand Down
7 changes: 7 additions & 0 deletions runtime/fastly/build-release-weval.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
cd "$(dirname "$0")" || exit 1
RUNTIME_VERSION=$(npm pkg get version --json --prefix=../../ | jq -r)
HOST_API=$(realpath host-api) cmake -B build-release-weval -DCMAKE_BUILD_TYPE=Release -DENABLE_BUILTIN_WEB_FETCH=0 -DENABLE_BUILTIN_WEB_FETCH_FETCH_EVENT=0 -DRUNTIME_VERSION="\"$RUNTIME_VERSION\"" -DWEVAL=ON
cmake --build build-release-weval --parallel 8
mv build-release-weval/starling.wasm/starling.wasm ../../starling-weval.wasm
mv build-release-weval/starling.wasm/starling-ics.wevalcache ../../
92 changes: 64 additions & 28 deletions src/compileApplicationToWasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { rmSync } from "node:fs";
import { isFile } from "./isFile.js";
import { isFileOrDoesNotExist } from "./isFileOrDoesNotExist.js";
import wizer from "@bytecodealliance/wizer";
import weval from "@cfallin/weval";
import { precompile } from "./precompile.js";
import { enableTopLevelAwait } from "./enableTopLevelAwait.js";
import { bundle } from "./bundle.js";
Expand All @@ -21,7 +22,9 @@ export async function compileApplicationToWasm(
enableExperimentalHighResolutionTimeMethods = false,
enablePBL = false,
enableExperimentalTopLevelAwait = false,
starlingMonkey = false
starlingMonkey = false,
enableAOT = false,
aotCache = '',
) {
try {
if (!(await isFile(input))) {
Expand Down Expand Up @@ -121,35 +124,68 @@ export async function compileApplicationToWasm(
}

try {
let wizerProcess = spawnSync(
`"${wizer}"`,
[
"--inherit-env=true",
"--allow-wasi",
"--dir=.",
...starlingMonkey ? [`--dir=${dirname(wizerInput)}`] : [],
`--wasm-bulk-memory=true`,
"-r _start=wizer.resume",
`-o="${output}"`,
`"${wasmEngine}"`,
],
{
stdio: [null, process.stdout, process.stderr],
input: wizerInput,
shell: true,
encoding: "utf-8",
env: {
ENABLE_EXPERIMENTAL_HIGH_RESOLUTION_TIME_METHODS:
enableExperimentalHighResolutionTimeMethods ? "1" : "0",
ENABLE_PBL: enablePBL ? "1" : "0",
...process.env,
},
if (enableAOT) {
const wevalBin = await weval();

let wevalProcess = spawnSync(
`"${wevalBin}"`,
[
"weval",
...aotCache ? [`--cache-ro ${aotCache}`] : [],
"--dir .",
...starlingMonkey ? [`--dir ${dirname(wizerInput)}`] : [],
"-w",
`-i "${wasmEngine}"`,
`-o "${output}"`,
],
{
stdio: [null, process.stdout, process.stderr],
input: wizerInput,
shell: true,
encoding: "utf-8",
env: {
ENABLE_EXPERIMENTAL_HIGH_RESOLUTION_TIME_METHODS:
enableExperimentalHighResolutionTimeMethods ? "1" : "0",
ENABLE_PBL: enablePBL ? "1" : "0",
...process.env,
},
}
);
if (wevalProcess.status !== 0) {
throw new Error(`Weval initialization failure`);
}
);
if (wizerProcess.status !== 0) {
throw new Error(`Wizer initialization failure`);
process.exitCode = wevalProcess.status;
} else {
let wizerProcess = spawnSync(
`"${wizer}"`,
[
"--inherit-env=true",
"--allow-wasi",
"--dir=.",
...starlingMonkey ? [`--dir=${dirname(wizerInput)}`] : [],
`--wasm-bulk-memory=true`,
"-r _start=wizer.resume",
`-o="${output}"`,
`"${wasmEngine}"`,
],
{
stdio: [null, process.stdout, process.stderr],
input: wizerInput,
shell: true,
encoding: "utf-8",
env: {
ENABLE_EXPERIMENTAL_HIGH_RESOLUTION_TIME_METHODS:
enableExperimentalHighResolutionTimeMethods ? "1" : "0",
ENABLE_PBL: enablePBL ? "1" : "0",
...process.env,
},
}
);
if (wizerProcess.status !== 0) {
throw new Error(`Wizer initialization failure`);
}
process.exitCode = wizerProcess.status;
}
process.exitCode = wizerProcess.status;
} catch (error) {
console.error(
`Error: Failed to compile JavaScript to Wasm: `,
Expand Down
26 changes: 26 additions & 0 deletions src/parseInputs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ export async function parseInputs(cliInputs) {
let enableExperimentalTopLevelAwait = false;
let starlingMonkey = true;
let enablePBL = false;
let enableAOT = false;
let customEngineSet = false;
let wasmEngine = join(__dirname, "../starling.wasm");
let aotCache = join(__dirname, "../starling-ics.wevalcache");
let customInputSet = false;
let input = join(process.cwd(), "bin/index.js");
let customOutputSet = false;
Expand All @@ -37,6 +39,10 @@ export async function parseInputs(cliInputs) {
enablePBL = true;
break;
}
case "--enable-experimental-aot": {
enableAOT = true;
break;
}
case "-V":
case "--version": {
return { version: true };
Expand Down Expand Up @@ -77,6 +83,14 @@ export async function parseInputs(cliInputs) {
}
break;
}
case "--aot-cache": {
if (isAbsolute(value)) {
aotCache = value;
} else {
aotCache = join(process.cwd(), value);
}
break;
}
default: {
// The reason this is not another `case` and is an `if` using `startsWith`
// is because previous versions of the CLI allowed an arbitrary amount of
Expand Down Expand Up @@ -119,10 +133,22 @@ export async function parseInputs(cliInputs) {
}
}
}

if (!starlingMonkey && enableAOT) {
// enableAOT requires StarlingMonkey.
console.log("AOT option is not compatible with pre-StarlingMonkey engine; please use StarlingMonkey.");
process.exit(1);
}
if (!customEngineSet && enableAOT) {
wasmEngine = join(__dirname, "../starling-weval.wasm");
}

return {
enableExperimentalHighResolutionTimeMethods,
enableExperimentalTopLevelAwait,
enablePBL,
enableAOT,
aotCache,
input,
output,
starlingMonkey,
Expand Down
Loading
Loading