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

Performance issue: Frequent font file I/O operations when rendering SVG with text #367

Open
iola1999 opened this issue Nov 21, 2024 · 0 comments · May be fixed by #366
Open

Performance issue: Frequent font file I/O operations when rendering SVG with text #367

iola1999 opened this issue Nov 21, 2024 · 0 comments · May be fixed by #366

Comments

@iola1999
Copy link

iola1999 commented Nov 21, 2024

Issue Description

When rendering SVG files containing large amount of text, I noticed there are frequent file I/O operations for reading font files, which significantly impacts performance. This becomes more noticeable as the number of text in the SVG increases.

Reproduction

I created a minimal reproduction case that demonstrates the issue:

import { Resvg } from "@resvg/resvg-js";

// SVG with large amount of text
const svgWithLargeAmountOfText = `<svg
  width="750px"
  height="3000px"
  viewBox="0 0 1500 6000"
  version="1.1"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  >
  <title>title</title>
  <g id="id1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
    <rect fill="#FFFFFF" x="0" y="0" width="1500" height="6000"></rect>
    <text
      id="id2"
      font-family="Alibaba PuHuiTi 2.0"
      font-size="72"
      font-weight="normal"
      fill="#000000"
    >
      <tspan x="10" y="100">
        ${`字`.repeat(500)}
      </tspan>
    </text>
  </g>
  </svg>
  `;

console.time("buildResvg");
const resvg = new Resvg(svgWithLargeAmountOfText, {
  font: {
    fontFiles: [
      // font file download from https://www.alibabafonts.com/#/font
      "/Users/xx/AlibabaPuHuiTi-2-35-Thin.ttf",
    ],
    loadSystemFonts: false,
  },
  background: "#ffffff",
});
console.timeEnd("buildResvg");

console.time("render");
resvg.render().asPng();
console.timeEnd("render");

On my MBP M2Pro, the result is as follows, the buildResvg stage takes 303ms.

image

When the amount of text is 3000, the buildResvg stage takes 1500ms.

image

Investigation

Through system-level logging, I observed that the program repeatedly reads font files from disk during the rendering process. This appears to be happening because the font files are being accessed multiple times rather than being loaded into memory once.

I believe this might be related to how the underlying dependencies (resvg/fontdb) handle font loading, rather than an issue with resvg-js itself.

image

Impact

  • Significant performance degradation when rendering SVGs with multiple text elements
  • Unnecessary I/O overhead
  • Potential system resource contention in high-load scenarios

Potential Solution

I've submitted a PR (#366 ) that adds a preloadFonts option to load font files into memory at initialization. While this doesn't address the root cause in the underlying libraries, it provides a practical workaround for resvg-js users experiencing performance issues with text-heavy SVGs.

const resvg = new Resvg(svgWithLargeAmountOfText, {
  font: {
    fontFiles: [
      // ttf font file download from https://www.alibabafonts.com/#/font
      "/Users/xx/AlibabaPuHuiTi-2-35-Thin.ttf",
    ],
    loadSystemFonts: false,
    preloadFonts: false,
  },
  background: "#ffffff",
});

After applying the optimization, the result is as follows, the buildResvg stage takes only 8ms(from 303ms).

image

When the amount of text is 3000, the buildResvg stage takes 15ms(from 1500ms, 100x faster 😄).

image

Would love to hear your thoughts on:

  1. Whether this is a known issue in the underlying dependencies
  2. If this local optimization makes sense as an interim solution
  3. If you'd prefer to handle this differently

Let me know if you need any additional information or benchmarks.

@iola1999 iola1999 linked a pull request Nov 21, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant