性能
并行性和并发性
Section titled “并行性和并发性”¥Parallelism and concurrency
Node.js 在处理对原生模块(例如 sharp)的异步调用时,使用 libuv 管理的线程池。
¥Node.js uses a libuv-managed thread pool when processing asynchronous calls to native modules such as sharp.
Sharp 可以并行处理的最大图片数量由 libuv 的 UV_THREADPOOL_SIZE
环境变量控制,默认为 4。
¥The maximum number of images that sharp can process in parallel is controlled by libuv’s
UV_THREADPOOL_SIZE
environment variable, which defaults to 4.
当使用超过 4 个物理 CPU 核心时,请在 Node.js 进程启动之前设置此环境变量以增加线程池大小。
¥When using more than 4 physical CPU cores, set this environment variable before the Node.js process starts to increase the thread pool size.
export UV_THREADPOOL_SIZE="$(lscpu -p | egrep -v "^#" | sort -u -t, -k 2,4 | wc -l)"
libvips 使用 glib 管理的线程池来避免生成新线程的开销。
¥libvips uses a glib-managed thread pool to avoid the overhead of spawning new threads.
用于并发处理每个图片的默认线程数与 CPU 核心数相同,但使用基于 glibc 且不使用 jemalloc 的 Linux 系统除外,此时默认线程数为 1
,以帮助减少内存碎片。
¥The default number of threads used to concurrently process each image is the same as the number of CPU cores,
except when using glibc-based Linux without jemalloc, where the default is 1
to help reduce memory fragmentation.
使用 sharp.concurrency()
管理每幅图片的线程数。
¥Use sharp.concurrency()
to manage the number of threads per image.
为了在使用默认 Linux glibc 内存分配器时减少内存碎片,请在 Node.js 进程启动之前设置 MALLOC_ARENA_MAX
环境变量以减少内存池的数量。
¥To reduce memory fragmentation when using the default Linux glibc memory allocator, set the
MALLOC_ARENA_MAX
environment variable before the Node.js process starts to reduce the number of memory pools.
export MALLOC_ARENA_MAX="2"
¥Benchmark
对该模块相对于替代方案的性能进行基准测试。
¥A test to benchmark the performance of this module relative to alternatives.
启用缓存(默认)并使用 8 个以上核心的计算机(尤其是具有较大 L1/L2 CPU 缓存的计算机)可以期待更高的 libvips 性能。
¥Greater libvips performance can be expected with caching enabled (default) and using 8+ core machines, especially those with larger L1/L2 CPU caches.
相关(解)压缩库的 I/O 限制通常将决定最大吞吐量。
¥The I/O limits of the relevant (de)compression library will generally determine maximum throughput.
¥Contenders
-
jimp v1.6.0 - 纯 JavaScript 中的图片处理。
¥jimp v1.6.0 - Image processing in pure JavaScript.
-
imagemagick v0.1.3 - 仅支持文件系统和 “has been unmaintained for a long time”。
¥imagemagick v0.1.3 - Supports filesystem only and “has been unmaintained for a long time”.
-
gm v1.25.1 - GraphicsMagick 的
gm
命令行实用程序的全功能封装器,但 “已停用”。¥gm v1.25.1 - Fully featured wrapper around GraphicsMagick’s
gm
command line utility, but “has been sunset”. -
sharp v0.34.3 / libvips v8.17.0 - 禁用 libvips 内的缓存以确保公平比较。
¥sharp v0.34.3 / libvips v8.17.0 - Caching within libvips disabled to ensure a fair comparison.
¥Environment
-
AWS EC2 us-west-2 c7a.xlarge (4x AMD EPYC 9R14)
-
Ubuntu 25.04
-
Node.js 24.3.0
-
AWS EC2 us-west-2 c8g.xlarge (4x ARM Graviton4)
-
Ubuntu 25.04
-
Node.js 24.3.0
任务:JPEG
Section titled “任务:JPEG”¥Task: JPEG
解压缩 2725x2225 JPEG 图片,使用 Lanczos 3 重采样(如果可用)将大小调整为 720x588,然后以 “quality” 设置 80 压缩为 JPEG。
¥Decompress a 2725x2225 JPEG image, resize to 720x588 using Lanczos 3 resampling (where available), then compress to JPEG at a “quality” setting of 80.
注意:jimp 不支持 Lanczos 3,而是使用双三次重采样。
¥Note: jimp does not support Lanczos 3, bicubic resampling used instead.
结果:JPEG (AMD64)
Section titled “结果:JPEG (AMD64)”¥Results: JPEG (AMD64)
包 | I/O | 操作数/秒 | 加速 |
---|---|---|---|
jimp | buffer | 2.40 | 1.0 |
jimp | file | 2.60 | 1.1 |
imagemagick | file | 9.70 | 4.0 |
gm | buffer | 11.60 | 4.8 |
gm | file | 11.72 | 4.9 |
sharp | stream | 59.40 | 24.8 |
sharp | file | 62.67 | 26.1 |
sharp | buffer | 64.42 | 26.8 |
结果:JPEG (ARM64)
Section titled “结果:JPEG (ARM64)”¥Results: JPEG (ARM64)
包 | I/O | 操作数/秒 | 加速 |
---|---|---|---|
jimp | buffer | 2.24 | 1.0 |
jimp | file | 2.47 | 1.1 |
imagemagick | file | 10.42 | 4.7 |
gm | buffer | 12.80 | 5.7 |
gm | file | 12.88 | 5.7 |
sharp | stream | 45.58 | 20.3 |
sharp | file | 47.99 | 21.4 |
sharp | buffer | 49.20 | 22.0 |
任务:PNG
Section titled “任务:PNG”¥Task: PNG
解压缩 2048x1536 RGBA PNG 图片,预乘 Alpha 通道,使用 Lanczos 3 重采样(如果可用)将大小调整为 720x540,取消预乘,然后使用 “default” zlib 压缩级别 6 压缩为 PNG,并且不使用自适应滤波。
¥Decompress a 2048x1536 RGBA PNG image, premultiply the alpha channel, resize to 720x540 using Lanczos 3 resampling (where available), unpremultiply then compress as PNG with a “default” zlib compression level of 6 and without adaptive filtering.
注意:jimp 不支持预乘/取消预乘。
¥Note: jimp does not support premultiply/unpremultiply.
结果:PNG (AMD64)
Section titled “结果:PNG (AMD64)”¥Results: PNG (AMD64)
包 | I/O | 操作数/秒 | 加速 |
---|---|---|---|
imagemagick | file | 6.06 | 1.0 |
gm | file | 8.44 | 1.4 |
jimp | buffer | 10.98 | 1.8 |
sharp | file | 28.26 | 4.7 |
sharp | buffer | 28.70 | 4.7 |
结果:PNG (ARM64)
Section titled “结果:PNG (ARM64)”¥Results: PNG (ARM64)
包 | I/O | 操作数/秒 | 加速 |
---|---|---|---|
imagemagick | file | 7.09 | 1.0 |
gm | file | 8.93 | 1.3 |
jimp | buffer | 10.28 | 1.5 |
sharp | file | 23.81 | 3.4 |
sharp | buffer | 24.19 | 3.4 |
运行基准测试
Section titled “运行基准测试”¥Running the benchmark test
需要 Docker。
¥Requires Docker.
git clone https://github.com/lovell/sharp.gitcd sharp/test/bench./run-with-docker.sh