Skip to content

shape_run is quadratic and basically freezes on large runs #523

Description

@norepro

Opening this issue because I think it is the root cause of pop-os/cosmic-files#1892 while I was looking into it.

Repro

Shape a large (100-200 KiB) string containing all NULL bytes or characters that do not exist in any font. It will hang.

Details

The shape_run function has quadratic performance when the run has any characters that cannot be rendered by the primary font. For each of these "missing" characters, they are resolved via fallback font and inserted one at a time into the run. If you have a very long string of "missing" characters (like the large null byte file bug above), it basically freezes. Technically it will complete, but not before the user thinks it's broken.

The big culprit seems to be the use of vectors instead of hashsets. Many of the operations are O(N). For example:

if !missing.contains(&start) || fb_missing.contains(&start) {

This one is within a loop:

missing.remove(missing_i);

And these two are potentially doing large memory moves:

let _glyph = glyphs.remove(i);

glyphs.insert(i, fb_glyph);

NB: It seems the devs are aware of the bad perf 😄️

//TODO: improve performance!

Possible Fix?

I think using HashSet<> instead of Vec<> would go a long way here. Use a hashset for the missing set of characters and maybe use it to index the positions of fallback glyphs in the run instead of removing/inserting repeatedly?

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

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions