Bun v1.0.20 reduces memory usage in fs.readlink
, fs.readFile
, fs.writeFile
, fs.stat
and HTMLRewriter
. Fixes a regression where setTimeout caused high CPU usage on Linux. HTMLRewriter.transform
now supports strings and ArrayBuffer
. fs.writeFile()
and fs.readFile()
now support hex
& base64
encodings. Bun.spawn
shows how much CPU & memory the process used.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
v1.0.15
- Fixes 23 bugs (addressing 117 👍 reactions),tsc
starts 2x faster. StableWebSocket
client, syntax-highlighted errors, cleaner stack traces, add custom test matchers withexpect.extend()
+ additional expect matchers.v1.0.16
- Fixes 49 bugs (addressing 38 👍 reactions). Concurrent IO for Bun.file & Bun.write gets 3x faster and now supports Google Cloud Run & Vercel, Bun.write auto-creates the parent directory if it doesn't exist,expect.extend
inside of preload works,napi_create_object
gets 2.5x faster, bugfix for module resolution impacting Astro v4 and p-limit, console.log bugfixesv1.0.17
- Fixes 15 bugs (addressing 152 👍 reactions). bun install postinstall scripts run for top 500 packages,bunx supabase
starts 30x faster thannpx supabase
,bunx esbuild
starts 50x faster thannpx esbuild
and bugfixes to bun installv1.0.18
- Fixes 27 bugs (addressing 28 👍 reactions). A hang impacting create-vite & create-next & stdin has been fixed. Lifecycle scripts reporting "node" or "node-gyp" not found has been fixed. expect().rejects works like Jest now, and more bug fixesv1.0.19
- Fixes 26 bugs (addressing 92 👍 reactions). Use @types/bun instead of bun-types. Fixes --frozen-lockfile bug. bcrypt & argon2 packages now work. setTimeout & setInterval get 4x higher throughput. module mocks in bun:test resolve specifiers. Optimized spawnSync() for large stdio on Linux. Bun.peek() gets 90x faster, expect(map1).toEqual(map2) gets 100x faster. Bugfixes to NAPI, bun install, and Node.js compatibility improvements
To install Bun:
curl -fsSL https://bun.sh/install | bash
npm install -g bun
brew tap oven-sh/bun
brew install bun
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun
To upgrade Bun:
bun upgrade
Reduced memory usage in node:fs
This release makes infrastructure changes that reduce memory usage for async work involving strings throughout Bun.
We've also improved internal reporting of memory allocations in debug builds, which helps us identify memory leaks.
fs.readlink
uses up to 2x less memory
After reading a symlink 1,000,000 times in parallel
Method | JavaScript runtime | Platform | RSS (MB) |
---|---|---|---|
fs.readlink | Bun v1.0.20 | macOS arm64 | 45 MB |
fs.readlink | Node.js v21.4.0 | macOS arm64 | 70 MB |
fs.readlink | Bun v1.0.19 | macOS arm64 | 107 MB |
fs.stat
uses up to 2x less memory
After stat'ing a file 1,000,000 times in parallel
Method | JavaScript runtime | Platform | RSS (MB) |
---|---|---|---|
fs.stat | Bun v1.0.20 --smol | macOS arm64 | 45 MB |
fs.stat | Bun v1.0.20 | macOS arm64 | 71 MB |
fs.stat | Node.js v21.4.0 | macOS arm64 | 70 MB |
fs.stat | Bun v1.0.19 | macOS arm64 | 107 MB |
fs.writeFile
memory leak fixed
Writing a 16 MB non-ascii string to disk 100 times
Method | JavaScript runtime | Platform | RSS (MB) |
---|---|---|---|
fs.writeFile | Bun v1.0.20 | macOS arm64 | 91 MB |
fs.writeFile | Node.js v21.4.0 | macOS arm64 | 130 MB |
fs.writeFile | Bun v1.0.19 | macOS arm64 | 1,696 MB |
HTMLRewriter.transform
now supports strings and ArrayBuffer
HTMLRewriter
lets you transform HTML on the fly. It's useful for things like:
- Rewriting URLs to point to a CDN
- Extracting metadata from HTML
- Getting all the images on a page
Bun's implementation of HTMLRewriter
now supports passing strings and ArrayBuffers to HTMLRewriter.transform
. Previously, you had to pass a Response
object.
Passing a string to HTMLRewriter.transform will parse the string as HTML and return a string.
const html = new HTMLRewriter()
.on("img", {
element(element) {
element.setAttribute("src", "https://example.com/image.png");
},
})
.on("title", {
element(element) {
element.setInnerContent("Hello world!");
},
})
.transform(
"<html><body><img src='image.png'><title>My page</title></body></html>",
);
console.log(html);
// <html><body><img src="https://example.com/image.png"><title>Hello world!</title></body></html>
Memory leak in HTMLRewriter fixed
A memory leak in HTMLRewriter has been fixed. This was caused by not calling the destructor at the appropriate time.
fs.readFile() and fs.writeFile() now support hex & base64 encodings
fs.readFile
and fs.writeFile
now support hex
and base64
encodings. This is useful for reading and writing binary files.
import { readFile, writeFile } from "fs/promises";
const buffer = await readFile("image.png", { encoding: "hex" });
await writeFile("image-copy.png", buffer, { encoding: "hex" });
Fixed: regression where setTimeout caused high CPU usage on Linux
There was a regression in Bun v1.0.19 where setTimeout
caused high CPU usage on Linux. This was fixed, thanks to @cirospaciari.
Bun.spawn now reports resourceUsage
Bun.spawn
& Bun.spawnSync
gets a resourceUsage
method, which reports CPU & memory usage for the process.
import { spawnSync } from "bun";
// for spawnSync, it is a property on the return value
const { resourceUsage } = spawnSync([
"bun",
"-e",
"console.log('Hello world!')",
]);
console.log(resourceUsage);
// in Bun.spawn, it is a function that you call
This prints:
ResourceUsage {
contextSwitches: {
voluntary: 0,
involuntary: 120,
},
cpuTime: {
user: 5578n,
system: 4488n,
total: 10066n,
},
maxRSS: 22020096,
messages: {
sent: 0,
received: 0,
},
ops: {
in: 0,
out: 0,
},
shmSize: 0,
signalCount: 0,
swapCount: 0,
}
Thanks to @cirospaciari for this contribution!
We used this to write tests to prevent the regression where setTimeout
caused high CPU usage on Linux from happening again.
Infrastructure improvements
In debug builds of Bun, we've added support for the 'malloc zone' feature of macOS to track memory allocations in native code more accurately. This helps us identify memory leaks.
This prints output like the below:
DefaultMallocZone:
blocks_in_use: 278
size_in_use: 2318192
max_size_in_use: 2696288
size_allocated: 19922944
WebKit Malloc:
blocks_in_use: 0
size_in_use: 0
max_size_in_use: 0
size_allocated: 0
Bun__Response:
blocks_in_use: 2
size_in_use: 240
max_size_in_use: 16976
size_allocated: 1048576
Bun__BufferOutputSink:
blocks_in_use: 1
size_in_use: 32
max_size_in_use: 16832
size_allocated: 1048576
We've also changed how we do cross-thread cloning of JavaScript strings. Previously, we sometimes cloned a string twice and then never used the first clone. This was extremely wasteful. Now, we only clone a string once and only if we definitely need to.
bun init
now uses @types/bun
bun init
now uses @types/bun
instead of bun-types
, and we've enabled some of the new options like verbatimModuleSyntax
.
Thanks to @ArnaudBarre for this contribution!