Closed hugovk closed 5 months ago
All modified and coverable lines are covered by tests :white_check_mark:
Comparison is base (
80da6be
) 94.21% compared to head (6279c94
) 94.38%.
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
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!