mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Improve Benchmarking page, small fixes (#2339)
* Improve benchmarking page * WIP * Add typescript instructions to hot * Document preload in Plugins. Fix loader in plugin types.
This commit is contained in:
@@ -21,7 +21,7 @@ $ bunx cowsay "Hello, world!" # execute a package
|
||||
|
||||
### Get started
|
||||
|
||||
{% block className="gap-[15px] grid grid-flow-row grid-cols-1 md:grid-cols-2" %}
|
||||
{% block className="gap-[10px] grid grid-flow-row grid-cols-1 md:grid-cols-2" %}
|
||||
{% arrowbutton href="/docs/installation" text="Install Bun" /%}
|
||||
{% arrowbutton href="/docs/quickstart" text="Do the quickstart" /%}
|
||||
{% arrowbutton href="/docs/cli/install" text="Install a package" /%}
|
||||
|
||||
@@ -180,8 +180,8 @@ export default {
|
||||
page("project/configuration", "Configuration", {
|
||||
description: `Bun's runtime is configurable with environment variables and the bunfig.toml config file.`,
|
||||
}),
|
||||
page("project/profiling", "Profiling", {
|
||||
description: `Bun is designed for performance. Learn how to benchmark and profile Bun yourself.`,
|
||||
page("project/benchmarking", "Benchmarking", {
|
||||
description: `Bun is designed for performance. Learn how to benchmark Bun yourself.`,
|
||||
}),
|
||||
page("project/developing", "Development", {
|
||||
description: "Learn how to contribute to Bun and get your local development environment up and running.",
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
Bun is designed for speed. Hot paths are extensively profiled and benchmarked. The source code for all of Bun's public benchmarks can be found in the [`/bench`](https://github.com/oven-sh/bun/tree/main/bench) directory of the Bun repo.
|
||||
|
||||
## Measuring time
|
||||
|
||||
To precisely measure time, Bun offers two runtime APIs functions:
|
||||
|
||||
1. The web-standard [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) function
|
||||
1. The Web-standard [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) function
|
||||
2. `Bun.nanoseconds()` which is similar to `performance.now()` except it returns the current time since the application started in nanoseconds. You can use `performance.timeOrigin` to convert this to a Unix timestamp.
|
||||
|
||||
## Benchmarking `Bun.serve`
|
||||
## Benchmarking tools
|
||||
|
||||
You will need an HTTP client which is at least as fast as `Bun.serve()`.
|
||||
When writing your own benchmarks, it's important to choose the right tool.
|
||||
|
||||
That means popular Node.js-based benchmarking tools like **autocannon is not fast enough**.
|
||||
- For microbenchmarks, a great general-purpose tool is [`mitata`](https://github.com/evanwashere/mitata).
|
||||
- For load testing, you *must use* an HTTP benchmarking tool that is at least as fast as `Bun.serve()`, or your results will be skewed. Some popular Node.js-based benchmarking tools like [`autocannon`](https://github.com/mcollina/autocannon) are not fast enough. We recommend one of the following:
|
||||
- [`bombardier`](https://github.com/codesenberg/bombardier)
|
||||
- [`oha`](https://github.com/hatoo/oha)
|
||||
- [`http_load_test`](https://github.com/uNetworking/uSockets/blob/master/examples/http_load_test.c)
|
||||
- For benchmarking scripts or CLI commands, we recommend [`hyperfine`](https://github.com/sharkdp/hyperfine). It's an easy way to compare
|
||||
|
||||
Recommended HTTP clients:
|
||||
|
||||
- [`bombardier`](https://github.com/codesenberg/bombardier)
|
||||
- [`oha`](https://github.com/hatoo/oha)
|
||||
- [`http_load_test`](https://github.com/uNetworking/uSockets/blob/master/examples/http_load_test.c)
|
||||
|
||||
## Measuring memory usage
|
||||
|
||||
@@ -26,8 +32,9 @@ The `bun:jsc` module exposes a few functions for measuring memory usage:
|
||||
```ts
|
||||
import { heapStats } from "bun:jsc";
|
||||
console.log(heapStats());
|
||||
|
||||
// will show something like this:
|
||||
```
|
||||
{% details summary="View example statistics" %}
|
||||
```ts
|
||||
{
|
||||
heapSize: 1657575,
|
||||
heapCapacity: 2872775,
|
||||
@@ -129,23 +136,18 @@ console.log(heapStats());
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /details %}
|
||||
|
||||
JavaScript is a garbage-collected language, not reference counted. It's normal and correct for objects to not be freed immediately in all cases, though it's not normal for objects to never be freed.
|
||||
|
||||
You can force garbage collection to run manually by calling:
|
||||
Tp force garbage collection to run manually:
|
||||
|
||||
```js
|
||||
const synchronously = true;
|
||||
Bun.gc(synchronously);
|
||||
Bun.gc(true); // synchronous
|
||||
Bun.gc(false); // asynchronous
|
||||
```
|
||||
|
||||
### JavaScript heap snapshot
|
||||
|
||||
Heap snapshots let you inspect what objects are not being freed. You can use the `bun:jsc` module to take a heap snapshot and then view it with Safari or WebKit GTK developer tools.
|
||||
|
||||
{% image alt="image" src="https://user-images.githubusercontent.com/709451/204429337-b0d8935f-3509-4071-b991-217794d1fb27.png" /%}
|
||||
|
||||
To generate a heap snapshot:
|
||||
Heap snapshots let you inspect what objects are not being freed. You can use the `bun:jsc` module to take a heap snapshot and then view it with Safari or WebKit GTK developer tools. To generate a heap snapshot:
|
||||
|
||||
```ts
|
||||
import { generateHeapSnapshot } from "bun";
|
||||
@@ -161,7 +163,14 @@ To view the snapshot, open the `heap.json` file in Safari's Developer Tools (or
|
||||
3. Click "JavaScript Allocations" in the menu on the left. It might not be visible until you click the pencil icon to show all the timelines
|
||||
4. Click "Import" and select your heap snapshot JSON
|
||||
|
||||

|
||||
|
||||
{% image alt="Import heap json" src="https://user-images.githubusercontent.com/709451/204428943-ba999e8f-8984-4f23-97cb-b4e3e280363e.png" caption="Importing a heap snapshot" /%}
|
||||
|
||||
Once imported, you should see something like this:
|
||||
|
||||
|
||||
{% image alt="Viewing heap snapshot in Safari" src="https://user-images.githubusercontent.com/709451/204429337-b0d8935f-3509-4071-b991-217794d1fb27.png" caption="Viewing heap snapshot in Safari Dev Tools" /%}
|
||||
|
||||
|
||||
### Native heap stats
|
||||
|
||||
@@ -10,14 +10,20 @@ $ bun --hot server.ts
|
||||
Starting from the entrypoint (`server.ts` in the example above), Bun builds a registry of all imported source files (excluding those in `node_modules`) and watches them for changes. When a change is detected, Bun performs a "soft reload". All files are re-evaluated, but all global state (notably, the `globalThis` object) is persisted.
|
||||
|
||||
```ts#server.ts
|
||||
// make TypeScript happy
|
||||
declare global {
|
||||
var count: number;
|
||||
}
|
||||
|
||||
globalThis.count = globalThis.count ?? 0;
|
||||
console.log(`Reloaded ${globalThis.count} times`);
|
||||
globalThis.count++;
|
||||
|
||||
// prevent `bun run` from exiting
|
||||
setInterval(function () {}, 1000000);
|
||||
```
|
||||
|
||||
If you run this file with `bun --hot server.ts`, you'll see the reload count increment every time you save the file. The call to `setInterval` is there to prevent the process from exiting.
|
||||
If you run this file with `bun --hot server.ts`, you'll see the reload count increment every time you save the file.
|
||||
|
||||
```bash
|
||||
$ bun --hot index.ts
|
||||
@@ -53,7 +59,13 @@ Unlike an explicit call to `Bun.serve`, the object-based syntax works out of the
|
||||
For more fine-grained control, you can use the `Bun.serve` API directly and handle the server reloading manually.
|
||||
|
||||
```ts#server.ts
|
||||
import type {Serve} from "bun";
|
||||
import type {Serve, Server} from "bun";
|
||||
|
||||
// make TypeScript happy
|
||||
declare global {
|
||||
var count: number;
|
||||
var server: Server;
|
||||
}
|
||||
|
||||
globalThis.count = globalThis.count ?? 0;
|
||||
globalThis.count++;
|
||||
|
||||
@@ -19,7 +19,15 @@ plugin({
|
||||
});
|
||||
```
|
||||
|
||||
To consume this plugin, import it at the top of your project's entrypoint, before any application code is imported.
|
||||
To consume this plugin, add this file to the `preload` option in your [`bunfig.toml`](/docs/project/configuration). Bun automatically loads the files/modules specified in `preload` before running a file.
|
||||
|
||||
```toml
|
||||
preload = ["./yamlPlugin.ts"]
|
||||
```
|
||||
|
||||
{% details summary="Usage eithout preload" %}
|
||||
|
||||
Alternatively, you can import this file manually at the top of your project's entrypoint, before any application code is imported.
|
||||
|
||||
```ts#app.ts
|
||||
import "./yamlPlugin.ts";
|
||||
@@ -28,6 +36,10 @@ import { config } from "./config.yml";
|
||||
console.log(config);
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Third party plugins
|
||||
|
||||
By convention, third-party plugins intended for consumption should export a factory function that accepts some configuration and returns a plugin object.
|
||||
|
||||
```ts
|
||||
|
||||
Reference in New Issue
Block a user