I recently wrote a Google Firebase Cloud function that resizes images on-the-fly and after having published that I discovered that sharp
is "better" than jimp
. And by better I mean better performance.
To reach this conclusion I wrote a simple trick that loops over a bunch of .png
and .jpg
files I had lying around and compare how long it took each implementation to do that. Here are the results:
Using jimp
▶ node index.js ~/Downloads Sum size before: 41.1 MB (27 files) ... Took: 28.278s Sum size after: 337 KB
Using sharp
▶ node index.js ~/Downloads Sum size before: 41.1 MB (27 files) ... Took: 1.277s Sum size after: 200 KB
The files are in the region of 100-500KB, a couple that are 1-3MB, and 1 that is 18MB.
So basically: 28 seconds for jimp
and 1.3 seconds for sharp
Bonus, the code
Don't ridicule me for my benchmarking code. These are quick hacks. Let's focus on the point.
sharp
function f1(sourcePath, destination) {
return readFile(sourcePath).then((buffer) => {
console.log(sourcePath, "is", humanFileSize(buffer.length));
return sharp(sourcePath)
.rotate()
.resize(100)
.toBuffer()
.then((data) => {
const destPath = path.join(destination, path.basename(sourcePath));
return writeFile(destPath, data).then(() => {
return stat(destPath).then((s) => s.size);
});
});
});
}
jimp
function f2(sourcePath, destination) {
return readFile(sourcePath).then((buffer) => {
console.log(sourcePath, "is", humanFileSize(buffer.length));
return Jimp.read(sourcePath).then((img) => {
const destPath = path.join(destination, path.basename(sourcePath));
img.resize(100, Jimp.AUTO);
return img.writeAsync(destPath).then(() => {
return stat(destPath).then((s) => s.size);
});
});
});
}
I test them like this:
console.time("Took");
const res = await Promise.all(files.map((file) => f1(file, destination)));
console.timeEnd("Took");
And just to be absolutely sure, I run them separately so the whole process is dedicated to one implementation.
Comments
Thanks for your post. I also used Jimp in the past, but I remember it worked slow. So I gonna try another library today. Let me go with sharp today.
I don't get why after you read file you still pass file path to sharp and jimp instead of giving them the already read buffer, which will make it faster.
Just for the demo/benchmark.
In some applications you might not have a reason to read the file in first, so you have to rely on `sharp(filePathAsString)`.
The reading of the file the first time is just so it can independently console log the size of the file it's about to test loading with sharp/jimp.