Plate 88
Sharp vs Jimp: 112ms vs 366ms Resize
sharp 0.35.5 vs Jimp 1.6.1 on one 1920×1080 JPEG → width 800 JPEG q80. Warm medians (7 rounds after 1 warm-up): sharp 112 ms / 142,435 B vs Jimp 366 ms / 269,590 B (~3.3×). Fixture /workspace/bench-sharp-jimp/.
Aditya Challa4 min read
I resized one 1920×1080 JPEG to width 800 at quality 80 seven times on this box: sharp 0.35 median 112 ms (142 KB out), Jimp 1.6 median 366 ms (270 KB out) — about 3.3× slower and nearly 2× larger for the same geometry.
Short answer: for Node image pipelines that can load a native binding, sharp was the default here. Jimp still fits when you need pure JavaScript with no libvips. No affiliate links in this post.
What I tested
- Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 00:18–00:19 IST.
- Versions: sharp 0.35.5 (libvips 8.18.7, mozjpeg); Jimp 1.6.1; Node 22.20.0.
- Fixture: /workspace/bench-sharp-jimp/. Source src-1920.jpg is a 1920×1080 JPEG (~981 KB) generated on-box. Task: resize to width 800 (height 450), encode JPEG quality 80. sharp used mozjpeg:true; Jimp used getBuffer(JimpMime.jpeg, {quality:80}).
- Timing: performance.now around each encode; 1 warm-up each, then 7 interleaved rounds. Outputs written to out/ for size checks.
- Findings: sharp median 112 ms (min 111 / max 120). Jimp median 366 ms (min 347 / max 463). Output bytes: sharp 142,435 B vs Jimp 269,590 B. Ratio ~3.3× on wall clock.
- One surprise: both landed at 800×450, but Jimp's JPEG was almost double the bytes at the same nominal quality 80.
- Not tested: WebP/AVIF, PNG, animated GIF, streaming pipelines, concurrency, browser Canvas, Squoosh, WASM codecs, Windows or macOS, serverless cold starts.
How wide was the resize gap?
| Library | Median wall | Min / Max | Output JPEG |
|---|---|---|---|
| sharp 0.35 resize+jpeg q80 | 112 ms | 111 / 120 | 142,435 B |
| Jimp 1.6 resize+jpeg q80 | 366 ms | 347 / 463 | 269,590 B |
Same source buffer, same target width, same box. sharp paid a one-time native install; after that every warm resize stayed near 112 ms. Jimp stayed in pure JS and paid for it on both time and bytes.
If you are weighing build or minify tools next, see SWC vs esbuild vs Babel and terser vs esbuild/swc minify. For bundle weight budgets after images, see size-limit vs bundlesize.
Does pure JS ever win this call?
Yes, when native bindings are blocked. Edge runtimes, locked-down CI images without libvips, or teams that refuse platform-specific binaries still pick Jimp or a WASM codec. On this Linux box with a normal npm install, that constraint did not apply, and sharp was faster and smaller.
I did not run Squoosh (@squoosh/lib); that path is a different maintenance story. Treat this post as sharp vs Jimp on one resize+JPEG job, not a full codec survey.
Should you switch image libraries?
| Situation | My pick |
|---|---|
| Node CI or server that can install sharp | sharp |
| Need pure JS, no native addons | Jimp |
| High-volume thumbnail farm | sharp |
| Tiny scripts, rare one-off edits | Either; Jimp is simpler to reason about |
| Shipping a Vite app and watching asset weight | Pair with Vite vs Parcel and source-map-explorer vs webpack-bundle-analyzer |
| Already on Astro/Vite image pipelines using sharp | Stay; do not add Jimp beside it |
Bottom line: on one 1920→800 JPEG resize, sharp returned in 112 ms median with a 142 KB file while Jimp needed 366 ms and 270 KB. Who should not switch: projects that cannot load native modules, or teams already happy with a WASM/browser encoder path.
How this was made: I generated one 1920×1080 JPEG on the ShopperCove box, installed sharp and Jimp, timed interleaved resize+encode rounds after a warm-up, recorded JSON medians and output bytes; the write-up was drafted with AI help and checked against that output.
Sources
- https://sharp.pixelplumbing.com/
- https://github.com/jimp-dev/jimp
- https://www.npmjs.com/package/sharp
- https://www.npmjs.com/package/jimp
- https://github.com/lovell/sharp
Related
- https://www.shoppercove.com/blog/size-limit-vs-bundlesize
- https://www.shoppercove.com/blog/vite-vs-parcel
- https://www.shoppercove.com/blog/swc-vs-esbuild-babel
- https://www.shoppercove.com/blog/terser-vs-esbuild-swc-minify
- https://www.shoppercove.com/blog/source-map-explorer-vs-webpack-bundle-analyzer
- https://www.shoppercove.com/blog/lightningcss-vs-postcss
- https://www.shoppercove.com/blog/rolldown-vs-rollup
- https://www.shoppercove.com/blog/vite-plus-1-0-unified-toolchain-october-2026
Lab evidence
What I found running this
Hands-on on ShopperCove box 6 Oct 2026 ~00:18–00:19 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). sharp 0.35.5 (libvips 8.18.7, mozjpeg) vs Jimp 1.6.1. Fixture /workspace/bench-sharp-jimp/: src-1920.jpg 1920×1080 JPEG ~981 KB; resize width=800 (450 tall), JPEG q80. 1 warm-up + 7 interleaved rounds. Medians sharp 112 ms (111–120) / 142,435 B vs Jimp 366 ms (347–463) / 269,590 B (~3.3×). Raw: /workspace/bench-sharp-jimp/res-sharp-jimp.json. Not tested: WebP/AVIF, PNG, concurrency, Squoosh, WASM, Windows/macOS, serverless cold starts. No affiliate.
Related links
Plate 73
volta vs fnm: Should You Switch? 14ms vs 17ms
volta 2.0.2 vs fnm 1.39.0 switching Node 20.19.2 ↔ 22.14.0: session A-then-B median 13.9 ms vs 17.0 ms; steady node -v 7.4 ms vs 6.4 ms (direct 4.7 ms).
5 Oct 2026
Plate 47
bun test vs Vitest: 136ms vs 1.67s on 300 Tests
bun test 1.4.2 vs Vitest 5.0.3 on 300 TypeScript tests in 60 files: warm wall medians 136 ms vs 1,673 ms (~12x); Vitest --no-isolate 765 ms (~5.6x). A 5-file vitest-API check (vi.fn, vi.mock, fake timers, spyOn, it.each, snapshot) passed 7/7 under Bun.
5 Oct 2026
Plate 46
esbuild-register vs jiti: 343ms vs 540ms Cold
esbuild-register 3.6.0 vs jiti 2.7.0 on a 61-file TypeScript graph: cold wall medians 343 ms vs 540 ms (~1.57x); after jiti disk cache warm, 185 ms vs esbuild-register 350 ms. Same printed result 970.
5 Oct 2026