Skip to content

Speed up calculate_content_widths: fused first-char flags on ShapedCluster + flat per-cluster scan - #48

Closed
nicoburns wants to merge 2 commits into
mainfrom
devin/1789646205-content-widths-main
Closed

nicoburns wants to merge 2 commits into
mainfrom
devin/1789646205-content-widths-main

Conversation

@nicoburns

@nicoburns nicoburns commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

LLM Contributions: Written by Devin (Cognition AI) under direction of @nicoburns.

Rebase of #46 / #32 onto main (3fdcdca, which includes upstream linebender#790 conditional hanging). Supersedes both. Recovers most of the calculate_content_widths regression from linebender#715 on a 250 KB real-text corpus:

build median ms min ms
v0.11.0 (flat ClusterData scan) 0.68–0.70 0.66
main (3fdcdca) 1.14–1.36 1.12
this PR 0.77–0.88 0.75

CPU-pinned, interleaved, n=12 x 3; widths-result identical (min: 1160.2813, max: 17458.617).

Commit 1 — engine: ShapedClusterFlags has 5 free bits; they now hold the first character's Boundary (2 bits) and Whitespace (3 bits — all 8 variants), set in process_shaped_clusters::flush from first_character.info (already loaded there). Additive API on ShapedCluster: boundary_before(), whitespace(), char_len(). ShapedCluster stays 20 bytes. (The commit message mentions the layout use; that lives in commit 2.)

Commit 2 — layout (+ engine round-trip test for the flag decode): when the run has no letter/word spacing (the common case), calculate_content_widths scans shaped_clusters directly instead of atoms_start():

  • break/newline checks only on atom-start clusters (i == 0 || is_grapheme_start()); a skip_atom flag skips a Newline atom's continuation clusters exactly like the atom loop's continue;
  • hanging accumulator updated per cluster (if cluster_hangs { += advance } else { = 0 }) — with no gaps this is equivalent to atom_hanging_advance's "hangs entirely / hangs partially from the logical end" rule;
  • whitespace_hangs(first char, style) is checked before char_len() == 1, so letters never load chars_range; multi-char clusters check every character with its own style, as atom_hanging_advance does;
  • hangs_conditionally is set from the cluster's style; the atom loop uses the atom's first-character style, which only differs for mixed-style multi-cluster atoms (the edge case already flagged in Implement CSS's conditional hanging of whitespace linebender/parley#790 review).

Runs with spacing keep the existing atoms_start() loop (it needs Atom for spacing.atom_advance / atom_hanging_advance).

A measurement-only variant with no hanging logic at all runs at ~0.60 ms, so the remaining gap to 0.11 is the hanging-whitespace semantics 0.11 didn't have, not the split data model.

Changelog: None

Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/2564f38c1f574d04ac6e9a57a7284d93
Open in Devin Desktop: https://dioxus.staging.devinenterprise.com/desktop/session/2564f38c1f574d04ac6e9a57a7284d93?variant=devin-insiders

@staging-devin-ai-integration

Copy link
Copy Markdown

I'll fix CI failures and address comments from users with write access that start with 'DevinAI' or '@devin'.

  • Disable automatic comment, CI, and merge conflict monitoring

…r; use it in calculate_content_widths

The width scan no longer touches the character array in its fast path:
boundary (2 bits) and whitespace class (3 bits) of a cluster's first
character are stored in the free bits of ShapedClusterFlags at shape time.
calculate_content_widths walks shaped clusters by index and only slices
into characters for multi-cluster/multi-character atoms.
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.

1 participant