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
Don’t calculate whole sets of unicode codepoints #1984
Conversation
thanks. You only timed the module loading time. It would be interesting to benchmark also the time it takes to run the |
As I was expecting, running import timeit
num_executions = 1000
total_time = timeit.timeit(
"bits = intersectUnicodeRanges(random.choices(range(0x110000), k=1000))",
setup="import random; from fontTools.ttLib.tables.O_S_2f_2 import intersectUnicodeRanges",
number=num_executions,
)
print(total_time / num_executions) With the current set implementation, on my MBP, I get:
With your range and for-loop based implementation, I get:
That is, almost 30 times slower. I am still not 100% convinced that your solution would be preferable. |
That’s not exactly true, because the module launches 3 unit tests…
… but you’re right: having some speed improvement for the set generation + 3
👍
Storing 130 MB in RAM during the whole execution time of the program is really bad for my use cases, but I get your point. I’ll try to improve my solution. |
I’ve changed the implementation, here are the results using the script you provided. Before: 0.82 ms / loop, 147 MB RAM
After: 0.85 ms / loop, 13 MB RAM
|
Nice! |
Another approach would be to special-case the non-BMP codepoints, as that makes up more than 81% of the current set-based data set. |
New results are equivalent, with less code.
I’m sure that it could be even better, but I think that it’s good enough for now 😉. Thanks a lot for the quick review. |
_getUnicodeRangeSets used to calculate sets containing lots of numbers, only to get intersections between a set and ranges. Creating and manipulating a lot of big sets requires a lot of memory. The function has been replaced by _getUnicodeRanges, returning a list of range starts boundaries and a list of range stops + corresponding bits. Tests on intersectUnicodeRanges save about 130 MB (!) of RAM, with no significant speed penalty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
_getUnicodeRangeSets
used to calculate sets containing lots of numbers, only to get intersections between a set and ranges. Creating and manipulating a lot of big sets is both slow and memory consuming.The function has been replaced by
_getUnicodeRanges
, returning ranges instead of sets. Ranges are both really lightweight and really fast.Tests on intersectUnicodeRanges are now 3 times faster and save about 130 MB (!) of RAM.
Before: 0.28 seconds, 148 MB RAM
After: 0.08 seconds (-70%), 14 MB RAM (-90%)