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:
Colin McDonnell
2023-03-07 17:44:05 -08:00
committed by GitHub
parent 1d2b0bbc98
commit 9bf4d9b8a2
9 changed files with 79 additions and 31 deletions

View File

@@ -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" /%}

View File

@@ -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.",

View File

@@ -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](https://user-images.githubusercontent.com/709451/204428943-ba999e8f-8984-4f23-97cb-b4e3e280363e.png)
{% 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

View File

@@ -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++;

View File

@@ -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