Repository navigation
perf(native): parse each font face once, and load CJK faces when CJK text comes up - #928
Merged
Merged
Conversation
The window asked for the same font file several times: the interface and the terminal set in one family, and the bold face fontconfig answers for both semibold and bold. Each ParseFace parsed the file's tables and every glyph outline again, about 30 MB for a Nerd Font face. Parsed faces are now kept by location under a weak pointer and shared while something holds them, so a family let go (a font picker's sample, the interface font before a change) is still freed. With ZedMono Nerd Font Mono for the interface, the terminal and the editor, the interface and terminal fonts drop from 246 MB to 175 MB of live heap.
An interface in a language other than Chinese, Japanese or Korean loaded a CJK font at start for the Han it might draw in a branch or a title, 56 MB with wqy-zenhei, whether any came up or not. The interface's shaper now leaves the CJK faces out until it is asked to draw Han, kana or Hangul: the fork's text.WithOutsideCollection reports a rune none of its faces draws, the window marks it, and on the next frame builds the shaper again with the faces, picked by the same rules. Until then the system font the shaper falls back to draws it. A CJK interface language loads them at start as before. Bumps lichdotdev/gio to 16fb1737 (branch lich), which carries WithOutsideCollection and merges upstream's main. With no CJK on screen the interface and terminal fonts take 119 MB of live heap, down from 175 MB.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A heap profile of a real window (
LICH_NATIVE_PPROF) 36 s after start showed 403 MB in use, about 240 MB of it fonts parsed at start. Two causes, one commit each.perf(fonts)). The window asked for the same file several times: the interface and the terminal set in one family, and the bold face fontconfig answers for both semibold and bold. EachParseFaceparsed the file's tables and every glyph outline again, about 30 MB for a Nerd Font face. Parsed faces are now kept byLocationunder aweak.Pointerand shared while something holds them, so a family that is let go (a font picker's sample, the interface font before a change) is still freed; a plain cache would have kept every sampled family for the run.perf(native)). An interface in a language other than Chinese, Japanese or Korean loaded a CJK font at start, 56 MB with wqy-zenhei, whether any Han came up or not. Gio parses every face of a shaper's collection when the shaper is built, so holding one back needs to know when text asks for it: the fork gainstext.WithOutsideCollection, called with each rune none of the collection's faces draws. The window marks the first Han, kana or Hangul and, on the next frame, builds the interface's shaper again with the CJK faces, picked by the same rules (hanFaces, weights covered). Until that frame the system font the shaper falls back to draws the rune. A CJK interface language loads them at start, as before.The fork commit is
lichdotdev/gio@07547a4don branchlich, merged with upstream'smain(16fb1737), whichnative/go.modnow points at.Measured
Live heap held by the interface and terminal fonts, with ZedMono Nerd Font Mono for the interface, the terminal and the editor, the interface in English:
Test plan
gofmt,go vet ./...,go test ./...innative/TestParseFaceSharesAFaceWhileItIsHeld(fails without the sharing, and fails with a cache that holds faces strongly),-race -count=20TestCJKFacesJoinTheInterfaceOnceCJKTextComesUp(fails with the CJK faces loaded at start, and fails without the rebuild on the next frame)TestShaperReportsRunesOutsideCollection;go test ./text/after the upstream mergeGOOS=darwinandGOOS=windowsgo vet ./fonts/