Skip to content

[Bug]: Rust conversion gets very slow when many fonts are registered #164

Description

@sverrejb

MiniPdf implementation

Rust

MiniPdf version

minipdf 0.6.0 and minipdf-cli 0.6.0, from crates.io

Authoring application

Microsoft Office

Authoring application version

No response

Environment

MiniPdf CLI, MiniPdf library

Runtime or host details

Rust 1.97.1 stable

Operating system

MacOS 15.7.9 arm64. Also seen on Ubuntu 26.04 x64.

Minimal test example

minipdf convert longDocument.docx --fonts <folder with many fonts> -o out.pdf

Expected: sub-second conversion
Actual: hundreds of seconds long conversion

Input files

Not super relevant. It is not file specific.

Additional context

I was comparing the different solutions for docx to pdf conversion, and noticed that the Minipdf rust CLI was very slow for larger files. In my benchmark I supply a large font directory with and run the conversions against a lot of files, some of them sort of large. 

It gets worse in two directions at once: more fonts, and more text.

| fonts registered | 2 words | 4900 words | 35300 words |
| ---------------- | ------- | ---------- | ----------- |
| 10               | 0.02 s  | 0.31 s     | 2.6 s       |
| 309              | 0.12 s  | 8.4 s      | 84 s        |

Thirty times more fonts made the long document thirty times
slower, while the short one stayed fast. A 122-page document
with 309 fonts took nearly a minute and a half on my m4 Macbook Pro.

Font file size does not matter, only the number of fonts.

## How to reproduce

1. Copy any font file 300 times into an empty folder, each with a different
   name.
2. Convert any DOCX with a few thousand words, pointing the fonts option at
   that folder.
3. Convert it again against a folder holding only 10 of the copies.

## Likely cause

From what I can tell, the font fallback loops over every registered font and parses it from raw bytes, for each character in the document.

## Suggested fix

The .NET version already handles this well. It parses each registered font once
per conversion and keeps its character map. Its cost grows with the number of
fonts, but not with document length.

The Rust version could do the same:

- Parse each font once and keep the result, instead of re-parsing per character.
- Even better: build the character-to-font map once and keep it for the life of the
  process, so later conversions reuse it.
Passing font data by reference instead of copying it into each document would
also cut memory use.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions