@sdxc/bench
Bundle-weight and HTTP latency budgets for packages and running apps
- Installs with
- @sdxc/cli@sdxc/duration@sdxc/result
- Depends on
esbuildremix- Source
- packages/bench
Bundle-weight and HTTP latency budgets for packages and running apps.
Hold a package entry to a gzipped size after a minified browser bundle, and sample latency against a URL that is already running.
Installation
npm add @sdxc/bench@sdxc/result and
@sdxc/duration install alongside.
Usage
Weigh an entry point
import { weigh } from "@sdxc/bench";
import { unwrap } from "@sdxc/result";
import { expect, test } from "vitest";
test("the format entry stays small", async () => {
let weight = unwrap(await weigh(new URL("./index.ts", import.meta.url).pathname));
expect(weight.gzipped).toBeLessThan(25 * 1024);
});The build targets the browser with every dependency inlined, so the number covers what a consumer pulls in. Gzipped size is the budget; minified is reported beside it for diagnosis.
Sample HTTP latency
import { sampleHttp } from "@sdxc/bench";
import { expect, test } from "vitest";
test("the health endpoint answers within budget", async () => {
let report = await sampleHttp({
url: "http://127.0.0.1:8787/health",
requests: 20,
concurrency: 5,
timeoutMs: 5_000,
});
expect(report.failures).toBe(0);
expect(report.p95).toBeLessThan(200);
expect(report.p99).toBeLessThan(500);
});failures counts requests that errored or timed out; ok is the rest of
requests. Time budgets on the command line accept
DurationInput: a string such as
"200ms" or a bare millisecond number.
Command line
With @sdxc/kit installed,
sdxc pkg bench runs the same checks from a terminal:
sdxc pkg bench --help
sdxc pkg bench weigh ./src/index.ts --max-gzipped 25600
sdxc pkg bench http https://example.com/ --requests 20 --p95 200ms --json--timeout, --p50, --p95, --p99 and --mean accept a
duration string (200ms, 5s)
or a bare millisecond number (200). Exit 1 when a budget fails or every
request errors; exit 2 for usage or an invalid duration.
API
weigh(entry: string, root?: string): Promise<Result<Weight, WeightError>>
Bundles entry for the browser (minified, dependencies inlined) from root
(default process.cwd()) and returns { minified, gzipped } in bytes.
assertWeight(weight, budget, entry?): Result<Weight, WeightError>
Answers a Result when weight.gzipped exceeds budget.maxGzipped, or when
optional budget.maxMinified is set and missed. Used by the CLI's
--max-gzipped flag; in tests, compare weight.gzipped with an expectation.
sampleHttp(options): Promise<HttpReport>
Issues requests with at most concurrency in flight, timing each with
performance.now(). The report's ok / failures split those attempts, and
min / mean / p50 / p95 / p99 / max cover the successful samples only.
assertHttpBudgets(report, budgets): Result<HttpReport, HttpBudgetError>
Answers a failure when a declared p50 / p95 / p99 / mean ceiling
(milliseconds) is exceeded. Used by the CLI; in tests, compare the report's
percentiles with expectations.
budgetMs(input) / parseBudgetFlag(text)
Normalize a DurationInput or a
CLI flag ("200" / "200ms") to milliseconds.