Skip to content
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

Cache repeated COLR subtables (2) #3221

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open

Conversation

anthrotype
Copy link
Member

Some improvements to #3215 to use pickle (faster than json), sha256 for the digest to mitigate collisions, and a LRU cache to avoid it growing unbounded.
I'm still unsure regarding the cache max size (I used 128 like lru_cache but don't know what a good number is in general for this task).
I'm also hesitant to enable this unconditionally and would rather it be opt in, as it's not guaranteed to lead to faster builds given the overhead of pickling+hashing objects mutliple times (the TableBuilder.build is called recursively for each struct fields in a table tree).

@anthrotype anthrotype changed the base branch from cache-colr-builds to main July 24, 2023 08:31
@simoncozens
Copy link
Collaborator

Using paintcompiler on Bitcount:

FontTools main: 2:19.07 (peak memory usage 4.8G)
cache-color-builds: 54.015 (peak memory usage 236M)
cache-color-builds-2: 2:41.66 (peak memory usage 5G)

Probably better to do nothing than to do this.

@anthrotype
Copy link
Member Author

well.. that's strange, how come your branch where we don't manage the cache at all and let it grow unbounded actually reports using less memory? How did you measure?

@anthrotype
Copy link
Member Author

also note that #3215 has a bug which I fixed in 259e013, the cache key must also contain the class itself otherwise two objects with distinct classes but same data can be confused

@simoncozens
Copy link
Collaborator

Don't know. The TTX is different between the master build and my build, but visually it's the same. I'm measuring the memory footprint with "top", which I know isn't completely accurate, but it's not going to be an order of magnitude wrong either.

@anthrotype
Copy link
Member Author

if the ttx is different it must be a bug, because this optimization is only meant to speed things up but the end result ought to be identical

# Move to the end to mark it as most recently used
self.cache.move_to_end(cacheKey)
# return unique copies; pickle/unpickle is faster than copy.deepcopy
return pickle.loads(pickle.dumps(self.cache[cacheKey]))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ugly, even if faster than deepcopy. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you might get away without a copy whatsoever, no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe as an opt-in.

Copy link
Member Author

@anthrotype anthrotype Aug 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ugly, even if faster than deepcopy. :)

the whole point of this was to speed things up...

you might get away without a copy whatsoever, no?

I don't think so. If you use this to build master COLR tables that are then sent to varLib.merger to build variable COLR, the thing is updated in-place and you don't want shared objects. When decompiling otTables from binary, you do get distinct objects even when they were pointed to by same offset.

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.

None yet

3 participants