-
-
Notifications
You must be signed in to change notification settings - Fork 158
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
Speedup: lazy imports and remove import #276
Merged
Merged
Conversation
This file contains 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
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #276 +/- ##
==========================================
+ Coverage 94.21% 94.38% +0.16%
==========================================
Files 5 5
Lines 2387 2405 +18
==========================================
+ Hits 2249 2270 +21
+ Misses 138 135 -3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
hugovk
changed the title
Speedup: lazy import and replace imports
Speedup: lazy imports and remove import
Feb 2, 2024
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.
Command-line interfaces value speed, and unused imports can slow things down a lot.
We can use
python -X importtime
and tuna to identify bottlenecks: https://medium.com/alan/how-we-improved-our-python-backend-start-up-time-2c33cd4873c8For example:
We're using Python 3.13.0a3 here, because it already includes some optimisations of its own.
Baseline
Starting on
main
,prettytable
: 0.027 s (87.8%)And let's begin by zooming into
prettytable.prettytable
: 0.010s (32.8%)Lazy import json
json
is a good first target. Taking 0.001 s (2.7%), it's only used by one function to load from JSON, and another to save. If doing plain text tables (or HTML etc), you won't use them.Let's move the import into those two functions where it's actually needed:
Result:
prettytable.prettytable
: 0.009 s (30.3%)Lazy import random
random
is only used by a function to set random styles, and is mostly for fun. Lazy import it to save 0.001 s (1.8%):Result:
prettytable.prettytable
0.009 s (28.5%)Lazy import csv
Like
json
,csv
is only used for loading or saving CSV and takes 0.003 s (10.8%).Result:
prettytable.prettytable
0.008 s (27.1%)Lazy import copy
Used in three places: a function to return a copy of a table. Is this used much? And also in other functions, themselves used when getting a number of string, HTML, CSV, JSON, Latex versions of a table. That's quite a few, so will likely end up being imported anyway, but it's a simple change and we may save 0.001 s (2.7%) in a few places.
Result:
prettytable.prettytable
0.008 s (25.9%)Lazy import textwrap
Only used in one function when getting a string version of a table. I think a common operation, but again, a quick saving for those cases when not.
Result:
prettytable.prettytable
0.007 s (24.6%)Lazy import wcwidth
Called by one function, but itself called several times, mostly for getting string tables? Well, saving of 0.001 s (2.2%) if not needed.
Result:
prettytable.prettytable
0.007 s (23.0%)Lazy import html.escape
Only used when getting HTML versions of tables: 0.001 s (2.3%)
Result:
prettytable.prettytable
0.007 s (22.5%)Replace math.floor with int
For positive inputs
math.floor
andint
give the same results, we can avoid importingmath
to save a (rounded) 0.000 s (0.9%). We were callingint
on the result ofmath.floor
anyway!Result:
prettytable.prettytable
0.006 s (21.6%)Lazy import importlib.metadata
Finally, let's step out back to
prettytable
:importlib.metadata
takes a big chunk of the original: 0.015 s (50.9%)!We only use this to set
__version__
on the off-chance someone might access it:We can instead only import when
__version__
is accessed:Result:
prettytable
0.007 s (65.1%).Compare with our original
prettytable
: 0.027 s (87.8%), that's a big saving!This is an idealised result and in reality a few of these will be imported, based on the use case. Still, those that do apply will help CLIs.
A quick look at the remaining "big" ones:
typing
0.003 s (24.3%) - not easy to remove without removing type hints entirely. The stdlib has already optimisedtyping
for 3.13, so already better than before.re
0.002 s (18.5%) - used to compile a regex to save time later. Used before calculating widths. Could potentially be replaced with somestr.replace
calls. Something to consider another time.html.parser.HTMLParser
0.002 s (17.0%) - used to subclass. Could potentially be moved and only imported/created when needing to parse those things, but could technically change the public API. Something to consider another time.But we've achieved enough here for now!