Skip to content

perf(textkit): improve line slicing performance#3420

Open
wojtekmaj wants to merge 1 commit into
diegomura:masterfrom
wojtekmaj:wmaj/textkit-line-slicing-perf
Open

perf(textkit): improve line slicing performance#3420
wojtekmaj wants to merge 1 commit into
diegomura:masterfrom
wojtekmaj:wmaj/textkit-line-slicing-perf

Conversation

@wojtekmaj
Copy link
Copy Markdown
Contributor

@wojtekmaj wojtekmaj commented May 12, 2026

This improves textkit line slicing performance for long paragraphs without changing line-breaking behavior.

Changes:

  • use binary search in glyphIndexAt instead of scanning backward through the full glyph index array
  • count ligature offsets by scanning the local repeated-index cluster instead of slicing/filtering the whole prefix
  • build breakLines with push instead of copying the accumulated line array on every breakpoint

Measured in a downstream PDF generator with a single long left-aligned body paragraph:

Baseline, 200k chars: ~31.3s wall, ~43.5s CPU, ~3.38GB maxRSS
With these textkit changes: ~17.0s wall, ~26.4s CPU, ~3.33GB maxRSS

Together with #3421, this improves performance in the same downstream PDF generator by:

Baseline, 50k chars: ~2.4s wall, ~3.0s CPU, ~563MB maxRSS
With #3420 + #3421: ~713ms wall, ~1.11s CPU, ~291MB maxRSS

Baseline, 100k chars: ~8.1s wall, ~10.1s CPU, ~1.18GB maxRSS
With #3420 + #3421: ~1.21s wall, ~1.73s CPU, ~423MB maxRSS

Baseline, 200k chars: ~31.3s wall, ~43.5s CPU, ~3.38GB maxRSS
With #3420 + #3421: ~2.28s wall, ~2.96s CPU, ~513MB maxRSS

The memory profile is mostly unchanged with this PR alone because the dominant heap allocation comes from the Knuth-Plass active-node search, but the CPU/wall-time improvement is still measurable.

Copilot AI review requested due to automatic review settings May 12, 2026 11:25
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 12, 2026

🦋 Changeset detected

Latest commit: a2b98ae

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@react-pdf/textkit Patch
@react-pdf/layout Patch
@react-pdf/render Patch
@react-pdf/renderer Patch
@react-pdf/math Patch
@react-pdf/mermaid Patch
next-14 Patch
next-15 Patch
@react-pdf/vite-example Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves @react-pdf/textkit line slicing performance for long paragraphs while preserving existing line-breaking behavior.

Changes:

  • Optimize ligature offset calculation by scanning only the local repeated-index cluster in offset.
  • Replace the linear backward scan in glyphIndexAt with a binary search over glyphIndices.
  • Avoid repeated array copying in breakLines by accumulating lines via push.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
packages/textkit/src/run/offset.ts Reduces ligature offset computation from prefix slicing/filtering to a bounded backward scan.
packages/textkit/src/run/glyphIndexAt.ts Uses binary search to find the last glyph mapping for a given string index.
packages/textkit/src/engines/linebreaker/index.ts Builds the lines array via mutation (push) instead of repeated spreading during accumulation.
.changeset/smart-maps-pay.md Adds a patch changeset describing the performance improvement.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@wojtekmaj wojtekmaj force-pushed the wmaj/textkit-line-slicing-perf branch from 2165382 to a2b98ae Compare May 12, 2026 11:34
@wojtekmaj wojtekmaj changed the title Improve textkit line slicing performance perf(textkit): improve line slicing performance May 12, 2026
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 this pull request may close these issues.

2 participants