Repository navigation
Adds a new bench mechanism
#7669
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
Open
jasnell
wants to merge
24
commits into
main
Choose a base branch
from
jasnell/wd-bench
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+8,317
−117
Open
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
58fcc53
Add libm Rust dependency
jasnell b3a2aeb
Add histogram crate with an HdrHistogram core
jasnell 7d3596a
Add statistical analysis to the histogram crate
jasnell 4d815b9
Add histogram export and import
jasnell 5d4f642
Add quantile-respectful density estimation to the histogram crate
jasnell 0f426c6
Let wd_rust_crate tests embed data files
jasnell 9f586b8
Test the histogram crate for parity with Node.js
jasnell 7d86184
Add a C++ interface to the histogram crate
jasnell 40faa63
Add a process-wide bench mode
jasnell 5a6db84
Add the bench event schema
jasnell cf0689c
Add the bench handler and BenchController
jasnell 14c5f3f
Add run::bench()
jasnell 2e9a74f
Add the workerd bench subcommand
jasnell 12836c7
Skip tail workers under workerd bench
jasnell 29f48ad
Add wd_bench() and a TextEncoder benchmark
jasnell 9c444ce
Measure and subtract the bench runner's overhead
jasnell 020c1a4
Document workerd bench and wd_bench()
jasnell b841385
Add workerd bench --trace
jasnell b8f4de0
Unit-test fillBenchReport() instead of timing
jasnell 3670e20
Add just new-bench
jasnell 89c844e
Mention workerd bench in AGENTS.md
jasnell fa7a6e7
Make the histogram crate's tests large
jasnell ae33aad
Leave just generate-types' snapshot writable
jasnell 5f52464
Default workerd bench to the newest compat date
jasnell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,3 @@ | ||
| samples/nodejs-compat-streams-split2/split2.js | ||
| # Generated by src/rust/histogram/testdata/generate-node-golden.mjs. | ||
| src/rust/histogram/testdata/node-golden.json |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| """wd_bench definition""" | ||
|
|
||
| load("@workerd//:build/lint_test.bzl", "lint_test") | ||
| load("@workerd//:build/wd_test.bzl", "wd_cli_test") | ||
|
|
||
| _WORKERD = "//src/workerd/server:workerd_cross" | ||
|
|
||
| def wd_bench( | ||
| src, | ||
| data = [], | ||
| name = None, | ||
| args = [], | ||
| lint = True, | ||
| compat_date = "", | ||
| generate_all_compat_flags_variant = True, | ||
| generate_all_autogates_variant = True, | ||
| tags = [], | ||
| **kwargs): | ||
| """Defines benchmarks that run `workerd bench` with a particular config. | ||
|
|
||
| Args: | ||
| src: A config file defining the benchmarks, in the same format as wd_test()'s. (`name` is | ||
| derived from it if not specified.) The extensions `.wd-bench`, `.wd-test`, and `.capnp` are | ||
| permitted. | ||
| data: Additional files that the config file may embed. TypeScript files are compiled, as for | ||
| wd_test(). | ||
| args: Additional arguments to pass to `workerd bench`. | ||
| lint: If True (default), lint the JavaScript and TypeScript in `data`. | ||
| compat_date: If specified, the compat date for the default variant instead of `latest`, the | ||
| newest that the build supports. | ||
| generate_all_compat_flags_variant: If True (default), generate @all-compat-flags variants. | ||
| generate_all_autogates_variant: If True (default), generate @all-autogates variants. | ||
| tags: Tags for all targets. | ||
|
|
||
| The variants are `name@` (`compat_date`), `name@all-compat-flags` (2999-12-31), and | ||
| `name@all-autogates` (`compat_date` with all autogates). For each variant, this generates: | ||
| - <variant>: a target for `bazel run`, which measures the benchmarks and prints the results. | ||
| Arguments after `--` are passed to `workerd bench`, e.g. a filter or `--format=json`. It is | ||
| tagged `workerd-benchmark`. | ||
| - <variant>@smoke: a test that runs the benchmarks once each with `--quick`, to check that they | ||
| work. This isn't tagged `workerd-benchmark`, so CI runs it. | ||
| It also generates `name@benchmark.json`, the default variant's report as a build output, which | ||
| is off by default. | ||
|
|
||
| As for wd_test(), a writable disk service named TEST_TMPDIR, e.g. for Durable Object storage, | ||
| gets a new empty directory for every run. Any other disk service uses the path in the config. | ||
| """ | ||
| data = data + [src] | ||
|
|
||
| ts_srcs = [s for s in data if s.endswith(".ts")] | ||
| if ts_srcs: | ||
| data = data + [s.removesuffix(".ts") + ".js" for s in ts_srcs] | ||
|
|
||
| if name == None: | ||
|
jasnell marked this conversation as resolved.
|
||
| name = src.removesuffix(".capnp").removesuffix(".wd-test").removesuffix(".wd-bench") | ||
|
|
||
| if lint: | ||
| lint_srcs = [s for s in data if (s.endswith(".ts") or s.endswith(".mts") or s.endswith(".js") or s.endswith(".mjs")) and not s.startswith("../") and not s.startswith("//")] | ||
| if lint_srcs: | ||
| lint_test( | ||
| name = name, | ||
| eslintrc_json = "@workerd//tools:base.eslint.config.mjs", | ||
| tsconfig_json = "@workerd//tools:base.tsconfig.json", | ||
| srcs = lint_srcs, | ||
| data = ["tsconfig.json"] if ts_srcs else [], | ||
| no_copy_to_bin = [ | ||
| "@workerd//tools:base.eslint.config.mjs", | ||
| "@workerd//tools:base.tsconfig.json", | ||
| ], | ||
| ) | ||
|
|
||
| # Benchmarks usually measure current behavior, so unlike wd_test(), the default variant uses | ||
| # the newest compat date that the build supports rather than the oldest. | ||
| default_compat_args = ["--compat-date={}".format(compat_date or "latest")] | ||
| variants = [("@", default_compat_args)] | ||
| if generate_all_compat_flags_variant: | ||
| variants.append(("@all-compat-flags", ["--compat-date=2999-12-31"])) | ||
| if generate_all_autogates_variant: | ||
| variants.append(("@all-autogates", default_compat_args + ["--all-autogates"])) | ||
|
|
||
| workerd_args = ["$(location {})".format(_WORKERD), "bench", "$(location {})".format(src)] + args | ||
| for suffix, variant_args in variants: | ||
| _wd_bench_run( | ||
| name = name + suffix, | ||
| data = data + [_WORKERD], | ||
| args = workerd_args + variant_args, | ||
| tags = ["workerd-benchmark"] + tags, | ||
| **kwargs | ||
| ) | ||
| wd_cli_test( | ||
| name = name + suffix.removesuffix("@") + "@smoke", | ||
| src = src, | ||
| data = data + [_WORKERD], | ||
| args = workerd_args + variant_args + ["--quick"], | ||
| tags = tags, | ||
| **kwargs | ||
| ) | ||
|
|
||
| native.genrule( | ||
| name = name + "@benchmark.json", | ||
| # workerd is a source rather than a tool so that this uses the build that the other targets | ||
| # use, as wd_cc_benchmark()'s report does, rather than building it again for the exec | ||
| # configuration. | ||
| srcs = data + [_WORKERD], | ||
| outs = [name + ".benchmark.json"], | ||
| cmd = ("TEST_TMPDIR=$$(mktemp -d) && " + | ||
| "$(location {}) bench --format=json --output=\"$@\" $(location {}) {} " + | ||
| "-dTEST_TMPDIR=$$TEST_TMPDIR; status=$$?; rm -rf $$TEST_TMPDIR; exit $$status").format( | ||
| _WORKERD, | ||
|
jasnell marked this conversation as resolved.
|
||
| src, | ||
| " ".join(args + default_compat_args), | ||
| ), | ||
| tags = ["off-by-default", "benchmark_report", "workerd-benchmark"] + tags, | ||
| ) | ||
|
|
||
| # As for wd_test(), configs can declare a writable disk service named TEST_TMPDIR, e.g. for | ||
| # Durable Object storage. The smoke tests get Bazel's test temporary directory from wd_cli_test(); | ||
| # the run targets and the report create a new temporary directory and remove it afterwards. | ||
| _SH_TEMPLATE = """#!/bin/bash | ||
| set -euo pipefail | ||
| TEST_TMPDIR=$(mktemp -d) | ||
| trap 'rm -rf "$TEST_TMPDIR"' EXIT | ||
| "$@" -dTEST_TMPDIR="$TEST_TMPDIR" | ||
| """ | ||
|
|
||
| _WINDOWS_TEMPLATE = """@echo off | ||
| setlocal | ||
| set "WD_BENCH_TMPDIR=%TEMP%\\wd-bench-%RANDOM%%RANDOM%" | ||
| mkdir "%WD_BENCH_TMPDIR%" || exit /b 1 | ||
| %* -dTEST_TMPDIR=%WD_BENCH_TMPDIR% | ||
| set "STATUS=%ERRORLEVEL%" | ||
| rmdir /s /q "%WD_BENCH_TMPDIR%" | ||
| exit /b %STATUS% | ||
| """ | ||
|
|
||
| def _wd_bench_run_impl(ctx): | ||
| is_windows = ctx.target_platform_has_constraint(ctx.attr._platforms_os_windows[platform_common.ConstraintValueInfo]) | ||
| if is_windows: | ||
| executable = ctx.actions.declare_file("%s_wd_bench.bat" % ctx.label.name) | ||
| content = _WINDOWS_TEMPLATE | ||
| else: | ||
| executable = ctx.actions.declare_file("%s_wd_bench.sh" % ctx.label.name) | ||
| content = _SH_TEMPLATE | ||
| ctx.actions.write(output = executable, content = content, is_executable = True) | ||
|
|
||
| runfiles = ctx.runfiles(files = ctx.files.data) | ||
| for target in ctx.attr.data: | ||
| runfiles = runfiles.merge(target[DefaultInfo].default_runfiles) | ||
| return [DefaultInfo(executable = executable, runfiles = runfiles)] | ||
|
|
||
| # Bazel runs only executables that the rule creates, so this writes a script that runs its | ||
| # arguments, which wd_bench() sets to the workerd command line. | ||
| _wd_bench_run = rule( | ||
| implementation = _wd_bench_run_impl, | ||
| executable = True, | ||
| attrs = { | ||
| "data": attr.label_list(allow_files = True), | ||
| "_platforms_os_windows": attr.label(default = "@platforms//os:windows"), | ||
| }, | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.