6 ms·
I started building Bun a little over a year ago, and as of about 20 minutes ago, its in public beta One of the things I'm excited about is bun install. On Lin
by Jarred 4y ago
I started building Bun a little over a year ago, and as of about 20 minutes ago, its in public beta
One of the things I'm excited about is bun install.
On Linux, it installs dependencies for a simple Next.js app about 20x faster than any other npm client available today.
hyperfine "bun install --backend=hardlink" "yarn install --no-scripts" "npm install --no-scripts --ignore-scripts" "pnpm install --ignore-scripts" --prepare="rm -rf node_modules" --cleanup="rm -rf node_modules" --warmup=8
Benchmark #1: bun install --backend=hardlink
Time (mean ± σ): 25.8 ms ± 0.7 ms [User: 5.4 ms, System: 28.3 ms]
Range (min … max): 24.4 ms … 27.6 ms 76 runs
Benchmark #2: yarn install --no-scripts
Time (mean ± σ): 568.4 ms ± 15.3 ms [User: 781.6 ms, System: 497.4 ms]
Range (min … max): 550.8 ms … 604.5 ms 10 runs
Benchmark #3: npm install --no-scripts --ignore-scripts
Time (mean ± σ): 1.261 s ± 0.017 s [User: 1.719 s, System: 0.516 s]
Range (min … max): 1.241 s … 1.286 s 10 runs
Benchmark #4: pnpm install --ignore-scripts
Time (mean ± σ): 1.343 s ± 0.003 s [User: 601.3 ms, System: 151.6 ms]
Range (min … max): 1.339 s … 1.348 s 10 runs
Summary
'bun install --backend=hardlink' ran
22.01 ± 0.85 times faster than 'yarn install --no-scripts'
48.85 ± 1.51 times faster than 'npm install --no-scripts --ignore-scripts'
51.99 ± 1.45 times faster than 'pnpm install --ignore-scripts'
- the_duke 4y agoThe benchmark source code links on the homepage are "Not found". Also a few questions: What do you attribute the performance advantage to? How much of it is JavascriptCore instead of v8 versus optimized glue binding implementations in the runtime? If the latter, what are you doing to improve performance? Similarly for the npm client: how much is just that bun is the only tool in a compiled /GC free language versus special optimization work? How does Zigs special support for custom allocators factor in?
- Jarred 4y agowill fix the broken links shortly edit: should be fixed
- claytongulick 4y agoIt's a deeply impressive achievement, absolutely blows my mind that you were able to do it in a year.
- andai 4y agoDang, nice work! Any idea where the slowness comes from in the other tools, how Bun manages to be so much faster?
- nicoburns 4y agoYeah, the install function of npm/yarn/pnpm are all incredbly slow. And also seems to get slower super-linearly with the number of dependencies. I have one project where it can take minutes (on my 2015 MacBook - admittedly it’s quicker on my brand new machine) just to add one be dependency and re-resolve the lock file. If that can solved by a reliable tool I’d definitely switch!
- oreilles 4y agoThis is one of if not the most insane thing in web dev at the moment. Git can diff thousand of files between two commit in less time than it takes to render the result on screen. But somehow it can take actual minutes to find out where to place a dependency in a simple tree with npm. God, why ?
- capableweb 4y ago> it can take actual minutes to find out where to place a dependency in a simple tree with npm. God, why ? npm is famous for a lot of things & reasons, but none of those are "because it's well engineered". To this day, npm still runs the `preinstall` script after dependencies have actually been downloaded to your disk. It modifies a `yarn.lock` file if you have it on disk when running `npm install`. Lots of things like these, so that the install is slow, is hardly surprising.
- hoten 4y agoSince when would npm install modify a yarn lock file?
- rickstanley 4y agoI don't know exactly the "since when", but recently I was caught off guard when issuing `npm i` by mistake in a yarn project. It modifies "yarn.lock" by changing some, if not all, the registry from yarn pkg registry to npm package registry.
- deleted 4y ago
- zebracanevra 4y agoIt seems like bun caches the manifest responses. PNPM, for example, resolves all package versions when installing (without a lockfile), which is slower. The registry does have a 300 second cache time, so not faulting you there, but it means your benchmark is on the fully cached path, which you'd only hit when installing something for the first time. Subsequent installs would use the lockfile and bun and PNPM seem fast* in that case. If I install a simple nextjs app, then remove node_modules, the lockfile, and the ~/.bun/install/cache/*.npm files (i.e. keep the contents, remove the manifests) and then install, bun takes around ~3-4s. PNPM is consistently faster for me at around ~2-3s. I'm not familiar with bun's internals so I may be doing something wrong. One piece of feedback, having the lockfile be binary is a HUGE turn off for me. Impossible to diff. Is there another format? * I will mention that even in the best case scenario with PNPM (i.e. lockfile and node_modules) it still takes 400ms to start up, which, yes, is quite slow. So every action APART from the initial install is much MUCH faster with bun. I still feel 400ms is good enough for a package manager which is invoked sporadically. Compare that to esbuild which is something you invoke constantly, and having that be fast is such a godsend.
- Jarred 4y ago> It seems like the main thing that bun does to stay ahead is cache the manifest responses. PNPM, for example, resolves all package versions when installing (without a lockfile), which is slower. This isn't the main optimization. The main optimization is the system calls used to copy/link files. To see the difference, compare `bun install --backend=copyfile` with `bun install --backend=hardlink` (hardlink should be the default). The other big optimization is the binary formats for both the lockfile and the manifest. npm clients waste a lot of time parsing JSON. The more minor optimizations have to do with reducing memory usage. The binary lockfile format interns the strings (very repetitive strings). However, many of these strings are tiny, so it's actually more expensive to store a hash and a length separately from the string itself. Instead, Bun stores the string as 8 bytes and one bit bit says whether the entire string is contained inside those 8 bytes or if it's a memory offset into the lockfile's string buffer (since 64-bit pointers can't use the full memory address and bun currently only targets 64-bit CPUs, this works) yarn also caches the manifest responses. > If I install a simple nextjs app, then remove node_modules, the lockfile, and the ~/.bun/install/cache/.npm files (i.e. keep the contents, remove the manifests) and then install, bun takes around ~3-4s. PNPM is consistently faster for me at around ~2-3s. This sounds like a concurrency bug with scheduling tasks from the main thread to the HTTP thread. I would love someone to help review the code for the thread pool & async io. > One piece of feedback, having the lockfile be binary is a HUGE turn off for me. Impossible to diff. Is there another format? If you do `bun install -y`, it will output as a yarn v1 lockfile. If you add this to your .gitattributes: *.lockb binary diff=lockb It will print the diff as a yarn lockfile.
- panzerboiler 4y agoCongratulations for the release! You are doing an impressive work with bun. I find particulary exciting the built-in sqlite, and I cannot wait to move all my projects to bun. Egoistically speaking (my 2012 mbp doesn't support AVX2 instructions), I hope that now that the project is public, since you are going to get a lot of issue reports about the failure on install, you will find some time to get back to issue#67. Thank you, and keep up the excellent work.
- syrusakbary 4y agoI'm ultra excited about Bun being finally open sourced, congrats on the amazing progress here Jarred! Since JSC is actually compilable to Wasm [1] and Zig supports WASI compilation, I wonder how easy would be to get it running fully in WAPM with WASI. Any thoughts on how feasible that should be? [1]: https://wapm.io/syrusakbary/jsc https://wapm.io/syrusakbary/jsc