-
Notifications
You must be signed in to change notification settings - Fork 147
Replace rustybuzz with HarfRust #417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Shaping performance is currently ~25-40% worse with HarfRust on Should we be caching the (/cc @dfrg) |
I agree with switching to harfrust. I will need to run lots of tests before, and I'll be busy for the next couple of weeks. |
I'm not exactly an expert, but everytime this comes up caching See also:
|
Maybe I still don't get how the shape plan API works, because the presence of the features array seems to indicate that each shape plan is meant to shape just one run of text. Sure, if you don't pass any features or each feature's span is infinite (as is the case here), then you can reuse them. But if an API consumer did genuinely want to pass in features that are only enabled for certain spans of text, then each shape plan would be tied to those features and the span indices to which they apply. |
I think the idea is that it's common to have large amounts of text with exactly the same font, features, etc. It's also common to have a few styles that are switched between, for example "switch into bold (or italic) for one word/sentence and then back to regular text" or even "switch into the heading style for a run of text and then back to the body style". So if you cache a few If you make that cache persistent, then you can also likely reuse that cache across frames where e.g. you change the text content but keep the same styles. |
The short answer is that you can reuse a plan as long the feature sets are the same with regard to tag, value and whether or not the feature is global. That is, the actual indices of the range limited features don’t matter when constructing a shape plan. This is the same behavior as HarfBuzz. edit: the reason is that non-global features require mask bits to be allocated and those allocations are fixed in the plan. |
This would be a great thing to put in the documentation! |
HarfRust recently had a new release, I'd recommend to update this PR to use it as it had performance improvements. |
Thanks! This next week I will be evaluating this. |
I've updated HarfRust, which provides a ~3% perf boost. Much more significantly, I've added a Current
This PR w/ `shape_plan_cache`
Not sure how I feel about adding another cache that the user has to clear on their own, or whether it's "cheating" the benchmark to use it. It looks like the most granular shaping level that's publicly exposed to the API consumer is line-level (via In general, caching seems to be a bit of a mess currently. There's |
Shape run cache is optional. We had a shape plan cache but it was removed for performance and memory usage reasons. So long as it won't grow forever and generally increases performance (try the UHDR sample linked in the README) then it should be ok. |
I agree with improving caching control generally. |
I put a simple "least recently added" At first, I tried storing just the single most recently used shape plan, but we shape whitespace separately, and its script will always be I added a benchmark which shapes |
Are there further optimizations you want to try, or is this ready for merge? |
This is ready to merge now. If I can think of any more optimizations, I'll leave them for the future. |
Rustybuzz has gone pretty much dormant, and HarfRust is its unofficial successor. It lives under the HarfBuzz organization, and instead of ttf-parser, it uses
read-fonts
from Fontations (which Swash also uses, albeit a different version).A few tweaks to the code here lets us get rid of ttf-parser as well, and use Skrifa (a higher-level library built atop
read-fonts
) instead.Once the version of Skrifa used in Swash is bumped, this should consolidate dependencies even further.
The last consumer of ttf-parser is fontdb, which uses an ancient version of it and apparently "isn't maintained anymore".
I can't see any difference in the Hebrew snapshot tests, unless VS Code's LFS diff previews are broken or something.It looks like these tests just always fail locally.