surfraw-tools icon indicating copy to clipboard operation
surfraw-tools copied to clipboard

Improve `mkelvis` startup time

Open Hoboneer opened this issue 5 years ago • 1 comments

On my machine, running PYTHONPROFILEIMPORTTIME=1 mkelvis --help >/dev/null using the mkelvis from commit 38fb4e05a3174145c4682c784ad4b4521911b651 installed using pipx, importing surfraw_tools.mkelvis takes ~54,000 us +- 4000 us. Of that 54,000 us, jinja2 takes 24,000 us +- 1000 us.

This is 67.5% of the total execution time (~0.08 s) to generate the github elvis from commit cebb1380b4fbc9022d9f8a8e55eb51bca60924e6 of my elvi repo. The command used to time it was ./elvi/github.sh-in | grep -vE '^\s*#' | xargs time mkelvis github.

I've looked at the jinja2 source code and there's a lot of stuff that happens during import. The dependency graph between modules is rather complex too (See pydeps output on src/jinja2/). It's hard to know what causes it all. Take note of jinja2._identifier for the one-liner (logical line) with the most impact on import time--its a pretty big regex.

import time: self [us] | cumulative | imported package
import time:       153 |        153 | zipimport
import time:       923 |        923 | _frozen_importlib_external
import time:        76 |         76 |     _codecs
import time:       501 |        577 |   codecs
import time:       394 |        394 |   encodings.aliases
import time:       813 |       1783 | encodings
import time:       213 |        213 | encodings.utf_8
import time:       129 |        129 | _signal
import time:       301 |        301 | encodings.latin_1
import time:        51 |         51 |     _abc
import time:       261 |        312 |   abc
import time:       297 |        609 | io
import time:        89 |         89 |   _locale
import time:       136 |        224 | _bootlocale
import time:        75 |         75 |       _stat
import time:       246 |        320 |     stat
import time:       159 |        159 |       genericpath
import time:       302 |        461 |     posixpath
import time:      1089 |       1089 |     _collections_abc
import time:       591 |       2459 |   os
import time:       198 |        198 |   _sitebuiltins
import time:       190 |        190 |     apport_python_hook
import time:       135 |        324 |   sitecustomize
import time:       631 |       3611 | site
import time:       311 |        311 |     types
import time:        93 |         93 |     _collections
import time:       837 |       1240 |   enum
import time:       137 |        137 |     _sre
import time:       308 |        308 |       sre_constants
import time:       388 |        695 |     sre_parse
import time:       312 |       1143 |   sre_compile
import time:        82 |         82 |     _functools
import time:        98 |         98 |         _operator
import time:       318 |        415 |       operator
import time:       156 |        156 |       keyword
import time:        53 |         53 |         _heapq
import time:       181 |        233 |       heapq
import time:       142 |        142 |       itertools
import time:       206 |        206 |       reprlib
import time:       928 |       2078 |     collections
import time:      1063 |       3222 |   functools
import time:       177 |        177 |   copyreg
import time:       695 |       6475 | re
import time:       167 |        167 |     surfraw_tools._package
import time:       192 |        359 |   surfraw_tools
import time:       168 |        168 |   __future__
import time:       955 |        955 |       locale
import time:      1089 |       2043 |     gettext
import time:       994 |       3037 |   argparse
import time:       357 |        357 |     warnings
import time:       162 |        162 |       fnmatch
import time:        97 |         97 |       errno
import time:       106 |        106 |       zlib
import time:       240 |        240 |         _compression
import time:       119 |        119 |           time
import time:       186 |        186 |                 token
import time:      1004 |       1190 |               tokenize
import time:       168 |       1357 |             linecache
import time:       402 |       1758 |           traceback
import time:       240 |        240 |           _weakrefset
import time:       802 |       2917 |         threading
import time:       296 |        296 |         _bz2
import time:       297 |       3748 |       bz2
import time:       307 |        307 |         _lzma
import time:       271 |        578 |       lzma
import time:        56 |         56 |       pwd
import time:        46 |         46 |       grp
import time:       592 |       5381 |     shutil
import time:        67 |         67 |       math
import time:      2446 |       2446 |         _hashlib
import time:        73 |         73 |         _blake2
import time:        95 |         95 |         _sha3
import time:       336 |       2948 |       hashlib
import time:        44 |         44 |         _bisect
import time:       204 |        247 |       bisect
import time:        43 |         43 |       _random
import time:       555 |       3858 |     random
import time:       506 |        506 |     weakref
import time:       453 |      10553 |   tempfile
import time:       186 |        186 |     collections.abc
import time:       669 |        669 |     contextlib
import time:      1708 |       2562 |   typing
import time:       449 |        449 |       surfraw_tools.validation
import time:       478 |        926 |     surfraw_tools.options
import time:      2289 |       3215 |   surfraw_tools.cliopts
import time:       211 |        211 |     importlib
import time:       144 |        144 |         importlib.machinery
import time:       525 |        669 |       importlib.abc
import time:       115 |        115 |           nt
import time:        85 |         85 |           nt
import time:        82 |         82 |           nt
import time:       259 |        540 |         ntpath
import time:       132 |        132 |           urllib
import time:      1124 |       1256 |         urllib.parse
import time:       873 |       2667 |       pathlib
import time:       463 |       3798 |     importlib.resources
import time:        56 |         56 |           _string
import time:       897 |        953 |         string
import time:       198 |        198 |         markupsafe._compat
import time:       173 |        173 |         markupsafe._speedups
import time:       682 |       2004 |       markupsafe
import time:        80 |         80 |               _struct
import time:       155 |        235 |             struct
import time:       268 |        268 |             _compat_pickle
import time:        84 |         84 |                 org
import time:        26 |        110 |               org.python
import time:        20 |        130 |             org.python.core
import time:       127 |        127 |             _pickle
import time:       973 |       1730 |           pickle
import time:       193 |       1923 |         jinja2._compat
import time:       199 |        199 |                 _json
import time:       536 |        734 |               json.scanner
import time:       509 |       1242 |             json.decoder
import time:       535 |        535 |             json.encoder
import time:       228 |       2004 |           json
import time:      1162 |       3166 |         jinja2.utils
import time:       384 |       5471 |       jinja2.bccache
import time:      1550 |       1550 |         jinja2.nodes
import time:       380 |        380 |           jinja2.exceptions
import time:       171 |        171 |             jinja2.visitor
import time:       271 |        442 |           jinja2.idtracking
import time:       160 |        160 |           jinja2.optimizer
import time:       877 |       1858 |         jinja2.compiler
import time:       593 |        593 |             jinja2.runtime
import time:       740 |       1332 |           jinja2.filters
import time:       987 |        987 |                 numbers
import time:       972 |       1959 |               _decimal
import time:       199 |       2157 |             decimal
import time:       407 |       2564 |           jinja2.tests
import time:       203 |       4098 |         jinja2.defaults
import time:        86 |         86 |             _ast
import time:       282 |        367 |           ast
import time:        56 |         56 |           unicodedata
import time:      1648 |       1648 |           jinja2._identifier
import time:      2023 |       4093 |         jinja2.lexer
import time:       353 |        353 |         jinja2.parser
import time:       818 |      12768 |       jinja2.environment
import time:       352 |        352 |       jinja2.loaders
import time:       358 |      20951 |     jinja2
import time:      1327 |      26285 |   surfraw_tools.common
import time:       416 |      46591 | surfraw_tools.mkelvis
import time:      1351 |       1351 | textwrap

Hoboneer avatar Jun 28 '20 05:06 Hoboneer

I don't think that the startup time can be decreased much further. The import time for jinja2 is ~45% (0 d.p.) of the total, taken from the above timings--which excludes the jinja2 imports that mkelvis also imports.

Further, I don't think that the jinja2 developers would like to increase the complexity of their codebase for little performance gain. I believe their main users are web developers so the startup time shouldn't matter too much in their case.

Hoboneer avatar Jul 01 '20 00:07 Hoboneer