mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
4d07ed0efa
Since "Deno.spawn()", "Deno.spawnSync()" and "Deno.spawnChild" are getting deprecated, this commits rewrites all tests and utilities to use "Deno.Command" API instead.
118 lines
3.2 KiB
JavaScript
Executable file
118 lines
3.2 KiB
JavaScript
Executable file
#!/usr/bin/env -S deno run --unstable --allow-read --allow-run
|
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
|
import { join, ROOT_PATH as ROOT } from "./util.js";
|
|
|
|
async function bashOut(subcmd) {
|
|
const { success, stdout } = await new Deno.Command("bash", {
|
|
args: ["-c", subcmd],
|
|
stdout: "piped",
|
|
stderr: "null",
|
|
}).output();
|
|
|
|
// Check for failure
|
|
if (!success) {
|
|
throw new Error("subcmd failed");
|
|
}
|
|
// Gather output
|
|
const output = new TextDecoder().decode(stdout);
|
|
|
|
return output.trim();
|
|
}
|
|
|
|
async function bashThrough(subcmd, opts = {}) {
|
|
const { success, code } = await new Deno.Command("bash", {
|
|
...opts,
|
|
args: ["-c", subcmd],
|
|
stdout: "inherit",
|
|
stderr: "inherit",
|
|
}).output();
|
|
|
|
// Exit process on failure
|
|
if (!success) {
|
|
Deno.exit(code);
|
|
}
|
|
}
|
|
|
|
async function availableBenches() {
|
|
// TODO(AaronO): maybe reimplement with fs.walk
|
|
// it's important to prune the walked tree so this is fast (<50ms)
|
|
const prunedDirs = ["third_party", ".git", "target", "docs", "test_util"];
|
|
const pruneExpr = prunedDirs.map((d) => `-path ${ROOT}/${d}`).join(" -o ");
|
|
return (await bashOut(`
|
|
find ${ROOT} -type d \
|
|
\\( ${pruneExpr} \\) \
|
|
-prune -false -o \
|
|
-path "${ROOT}/*/benches/*" -type f -name "*.rs" \
|
|
| xargs basename | cut -f1 -d.
|
|
`)).split("\n");
|
|
}
|
|
|
|
function latestBenchBin(name) {
|
|
return bashOut(`ls -t "${ROOT}/target/release/deps/${name}"* | head -n 1`);
|
|
}
|
|
|
|
function runFlamegraph(benchBin, benchFilter, outputFile) {
|
|
return bashThrough(
|
|
`sudo -E flamegraph -o ${outputFile} ${benchBin} ${benchFilter ?? ""}`,
|
|
// Set $PROFILING env so benches can improve their flamegraphs
|
|
{ env: { "PROFILING": "1" } },
|
|
);
|
|
}
|
|
|
|
async function binExists(bin) {
|
|
try {
|
|
await bashOut(`which ${bin}`);
|
|
return true;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
const { 0: benchName, 1: benchFilter } = Deno.args;
|
|
// Print usage if no bench specified
|
|
if (!benchName) {
|
|
console.log("flamebench.js <bench_name> [bench_filter]");
|
|
// Also show available benches
|
|
console.log("\nAvailable benches:");
|
|
const benches = await availableBenches();
|
|
console.log(benches.join("\n"));
|
|
return Deno.exit(1);
|
|
}
|
|
|
|
// List available benches, hoping we don't have any benches called "ls" :D
|
|
if (benchName === "ls") {
|
|
const benches = await availableBenches();
|
|
console.log(benches.join("\n"));
|
|
return;
|
|
}
|
|
|
|
// Ensure flamegraph is installed
|
|
if (!await binExists("flamegraph")) {
|
|
console.log(
|
|
"flamegraph (https://github.com/flamegraph-rs/flamegraph) not found, please run:",
|
|
);
|
|
console.log();
|
|
console.log("cargo install flamegraph");
|
|
return Deno.exit(1);
|
|
}
|
|
|
|
// Build bench with frame pointers
|
|
await bashThrough(
|
|
`RUSTFLAGS='-C force-frame-pointers=y' cargo build --release --bench ${benchName}`,
|
|
);
|
|
|
|
// Get the freshly built bench binary
|
|
const benchBin = await latestBenchBin(benchName);
|
|
|
|
// Run flamegraph
|
|
const outputFile = join(ROOT, "flamebench.svg");
|
|
await runFlamegraph(benchBin, benchFilter, outputFile);
|
|
|
|
// Open flamegraph (in your browser / SVG viewer)
|
|
if (await binExists("open")) {
|
|
await bashThrough(`open ${outputFile}`);
|
|
}
|
|
}
|
|
// Run
|
|
await main();
|