Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slow processing with composite SVG which contains <text> #2987

Closed
robinparisi opened this issue Nov 22, 2021 · 10 comments
Closed

Slow processing with composite SVG which contains <text> #2987

robinparisi opened this issue Nov 22, 2021 · 10 comments
Labels

Comments

@robinparisi
Copy link

robinparisi commented Nov 22, 2021

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.

@lovell
Copy link
Owner

lovell commented Nov 23, 2021

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.

@lovell lovell added question and removed triage labels Nov 23, 2021
@robinparisi
Copy link
Author

robinparisi commented Nov 24, 2021

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.

@yisibl
Copy link

yisibl commented Dec 27, 2021

In my MacBook: createimage: 1.097s

image

@lovell
Copy link
Owner

lovell commented Jan 24, 2022

@robinparisi Were you able to make any progress with this?

@robinparisi
Copy link
Author

robinparisi commented Jan 24, 2022

@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 :

Capture d’écran 2022-01-24 à 18 43 03

@lovell
Copy link
Owner

lovell commented Jan 26, 2022

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

@lovell
Copy link
Owner

lovell commented Jan 31, 2022

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.

@robinparisi
Copy link
Author

robinparisi commented Feb 2, 2022

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)

test-fonts

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

valgrind

@lovell
Copy link
Owner

lovell commented Feb 3, 2022

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

@lovell
Copy link
Owner

lovell commented Aug 24, 2022

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.

@lovell lovell closed this as completed Aug 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants