diff options
author | 2023-03-07 17:44:05 -0800 | |
---|---|---|
committer | 2023-03-07 17:44:05 -0800 | |
commit | 9bf4d9b8a24b930acaa14836884a68bbf6c7fefa (patch) | |
tree | e2829fbe66c0031df893ec0a18bf31146a768aa1 | |
parent | 1d2b0bbc98a388cdb7d3655a56333cac09c5a280 (diff) | |
download | bun-9bf4d9b8a24b930acaa14836884a68bbf6c7fefa.tar.gz bun-9bf4d9b8a24b930acaa14836884a68bbf6c7fefa.tar.zst bun-9bf4d9b8a24b930acaa14836884a68bbf6c7fefa.zip |
Improve Benchmarking page, small fixes (#2339)
* Improve benchmarking page
* WIP
* Add typescript instructions to hot
* Document preload in Plugins. Fix loader in plugin types.
-rwxr-xr-x | bench/react-hello-world/bun.lockb | bin | 0 -> 2630 bytes | |||
-rw-r--r-- | bench/react-hello-world/package.json | 16 | ||||
-rw-r--r-- | docs/index.md | 2 | ||||
-rw-r--r-- | docs/nav.ts | 4 | ||||
-rw-r--r-- | docs/project/benchmarking.md (renamed from docs/project/profiling.md) | 49 | ||||
-rw-r--r-- | docs/runtime/hot.md | 16 | ||||
-rw-r--r-- | docs/runtime/plugins.md | 14 | ||||
-rw-r--r-- | packages/bun-types/bun.d.ts | 4 | ||||
-rw-r--r-- | packages/bun-types/tests/array.test-d.ts | 5 |
9 files changed, 79 insertions, 31 deletions
diff --git a/bench/react-hello-world/bun.lockb b/bench/react-hello-world/bun.lockb Binary files differnew file mode 100755 index 000000000..6fd04cd03 --- /dev/null +++ b/bench/react-hello-world/bun.lockb diff --git a/bench/react-hello-world/package.json b/bench/react-hello-world/package.json new file mode 100644 index 000000000..b11485205 --- /dev/null +++ b/bench/react-hello-world/package.json @@ -0,0 +1,16 @@ +{ + "name": "react-hello-world", + "version": "1.0.0", + "description": "", + "main": "react-hello-world.node.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "Colin McDonnell", + "license": "ISC", + "dependencies": { + "react": "next", + "react-dom": "next" + } +} diff --git a/docs/index.md b/docs/index.md index be9051a9f..0426981c0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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" /%} diff --git a/docs/nav.ts b/docs/nav.ts index c5ff4b426..dfc9ee0d2 100644 --- a/docs/nav.ts +++ b/docs/nav.ts @@ -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.", diff --git a/docs/project/profiling.md b/docs/project/benchmarking.md index d734588b2..0e3578237 100644 --- a/docs/project/profiling.md +++ b/docs/project/benchmarking.md @@ -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 diff --git a/docs/runtime/hot.md b/docs/runtime/hot.md index 547728f4d..96571453c 100644 --- a/docs/runtime/hot.md +++ b/docs/runtime/hot.md @@ -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++; diff --git a/docs/runtime/plugins.md b/docs/runtime/plugins.md index de8885507..911d0ba1d 100644 --- a/docs/runtime/plugins.md +++ b/docs/runtime/plugins.md @@ -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 diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 3dffc21b2..7c43ebd3a 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -2484,7 +2484,7 @@ declare module "bun" { * * "css" will be added in a future version of Bun. */ - loader: "js" | "jsx" | "ts" | "tsx"; + loader: "js" | "jsx" | "ts" | "tsx" | "json" | "toml"; } interface OnLoadResultObject { @@ -2676,7 +2676,7 @@ declare module "bun" { */ builder: PluginBuilder, ): void | Promise<void>; - }): ReturnType<typeof options["setup"]>; + }): ReturnType<(typeof options)["setup"]>; /** * Deactivate all plugins diff --git a/packages/bun-types/tests/array.test-d.ts b/packages/bun-types/tests/array.test-d.ts index ac04c6b34..65295b3b1 100644 --- a/packages/bun-types/tests/array.test-d.ts +++ b/packages/bun-types/tests/array.test-d.ts @@ -1,5 +1,3 @@ -import { expectType } from "tsd"; - async function* listReleases() { for (let page = 1; ; page++) { const response = await fetch( @@ -16,4 +14,5 @@ async function* listReleases() { } const releases = await Array.fromAsync(listReleases()); -expectType<{ data: string }[]>(releases); + +export {}; |