Skip to content

Speed up calculate_content_widths on top of break-spaces (#820): fused cluster flags + flat per-cluster scan - #49

Closed
nicoburns wants to merge 4 commits into
devin/1789263416-break-spacesfrom
devin/1789647033-content-widths-820
Closed

nicoburns wants to merge 4 commits into
devin/1789263416-break-spacesfrom
devin/1789647033-content-widths-820

Conversation

@nicoburns

Copy link
Copy Markdown
Member

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

#48 rebased onto the break-spaces branch (#38 / upstream linebender#820, at f76e660), plus one extra commit so the flat scan keeps its speed with linebender#820's soft_line_break rule. Stacked on #38; supersedes #48.

Corpus benchmark (250 KB real text, calculate_content_widths, CPU-pinned, interleaved, n=12 x 3; widths-result identical):

build median ms min ms
v0.11.0 0.67–0.68 0.66
main (3fdcdca) 1.14–1.15 1.12
linebender#820 branch (f76e660) 1.35–1.37 1.31
linebender#820 + #48 rebased naively (calling soft_line_break per atom) 1.28–1.32 1.27
this PR 0.81–0.82 0.78

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. Additive API on ShapedCluster: boundary_before(), whitespace(), char_len(). ShapedCluster stays 20 bytes. (Message mentions the layout use; that's commit 2.)

Commit 2 — layout (+ flag round-trip test): for runs without letter/word spacing, calculate_content_widths scans shaped_clusters directly instead of atoms_start(): break/newline checks only on atom-start clusters (i == 0 || is_grapheme_start(), with skip_atom for a Newline atom's continuation clusters), hanging accumulator updated per cluster (if cluster_hangs { += advance } else { = 0 }, equivalent to atom_hanging_advance when there are no gaps), whitespace_hangs(first char, style) checked before char_len() == 1 so letters never load chars_range. Runs with spacing keep the atom loop.

Commit 3 — break-spaces in the flat scan: soft_line_break() reads characters[index-1] and characters[index] (plus their styles) per atom, which is what made the naive rebase lose most of the gain. The flat scan now evaluates the same rule from the cached flags: boundary_before() == Line && !is_break_space_class(whitespace, style) || is_break_space(characters[start-1]), and only does that (and the characters[start-1] load) when some style in the layout uses BreakSpaces (any_break_spaces, computed once per call); otherwise it's just boundary_before() == Line. is_break_space is split into is_break_space_class(whitespace, style) + the existing character-based wrapper.

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

…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.
@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

@staging-devin-ai-integration
staging-devin-ai-integration Bot force-pushed the devin/1789263416-break-spaces branch from e34ca89 to e628d13 Compare September 20, 2026 12:48
@nicoburns nicoburns closed this Sep 22, 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.

1 participant