sharp
sharp copied to clipboard
Slow processing with composite SVG which contains <text>
Hi,
I'm trying to add a text to my picture by using composite API and an SVG wich contains a <text>
element. When I remove <text>
, or try with a simple SVG, the process only takes a few ms (< 10ms) for one picture. As soon as I add a <text>
element, it takes many seconds (> 7s) to process. Below a simple example with a measurment of execution time.
const sharp = require('sharp')
;(async () => {
const overlay = `<svg width="200" height="200">
<text x="50%" y="50%" font-family="sans-serif" dominant-baseline="middle" font-size="30" text-anchor="middle">Lorem ipsum</text>
</svg>`
console.time('createimage')
await sharp(
{
create: {
width: 200,
height: 200,
channels: 4,
background: { r: 216, g: 216, b: 216 }
}
})
.composite([{
input: Buffer.from(overlay),
gravity: 'center'
}])
.png()
.toFile('test.png')
console.timeEnd('createimage')
})()
With result:
createimage: 7.377s
Informations:
Sharp : [email protected]
System:
OS: macOS Mojave 10.14.6
CPU: (12) x64 Intel(R) Core(TM) i7-8700B CPU @ 3.20GHz
Memory: 155.33 MB / 16.00 GB
Shell: 5.3 - /bin/zsh
Binaries:
Node: 14.18.1 - ~/.nvm/versions/node/v14.18.1/bin/node
npm: 6.14.15 - ~/.nvm/versions/node/v14.18.1/bin/npm
Interesting point: I've tried the same code on a colleague's mac computer with M1 chip and it took only ~70ms to process (and ~5ms without <text>
element).
I'm not sure it's directly related to this lib, I saw a few issues with SVG but none wich implies <text>
in the process with the composite API.
Hi, this sample code fails with Error: Image to composite must have same dimensions or smaller
.
If I change height="1000"
to height="200"
, or change height: 200
to height: 1000
, so the dimensions match, I consistently see times all below 30ms.
Are you using the prebuilt libvips binaries provided by sharp? Perhaps you've installed the vips
package via Homebrew? If the latter, it's possible there's a problem with font discovery on your machine.
Hey @lovell, thanks for the response.
You're absolutely right, there is an error with SVG height, I've edited the code.
Based on this page https://sharp.pixelplumbing.com/install, I've installed the lib with a simple npm i sharp
so I'm using the prebuilt version of libvips. I've checked Homebrew and no version is installed locally.
Edit: Is it possible than other libs installed locally like libpng
can interfere with Sharp? I'm not sure it's related but I prefere to check.
In my MacBook: createimage: 1.097s
@robinparisi Were you able to make any progress with this?
@lovell I couldn't find any reason at the moment. I've tried on multiple mac mini and except for the M1 one (wich is really fast anyway), it always takes more time with SVG text, by oposition to simple SVG with no text which is way faster.
I've also tried with node v16.13.2 :

Please can you profile this script via a tool such as callgrind.
Install via brew install valgrind
then run via valgrind --tool=callgrind node main.js
- this will produce a file called callgrind.out.xxxx
Please can you provide the output of running callgrind_annotate callgrind.out.xxxx
Quick thought: do you have fontconfig
installed? You can do this via brew install fontconfig
if not. This might make font discovery faster as it will cache filesystem lookups.
So, I had over 2000 fonts. I've tried to uninstall all my custom fonts and run the test script again. Execution time dropped under 500 ms. It seems that execution time is correlated to the number of fonts available (fontconfig is installed)

PS: I'm not sure I can install Valgrind from brew (not sure why atm)

Thanks for the update, this does sound like font discovery is the problem.
I hadn't realised valgrind is unavailable for macOS via homebrew, sorry. You might be able to use kcachegrind, which appears to be available via MacPorts - https://github.com/macports/macports-ports/tree/master/kde/kcachegrind4
Closing as there's probably nothing we can do in sharp for this. fontconfig provides the fc-cache
tool to build a cache of fonts so it doesn't have to "discover" them each time, which might help.