Open mlucool opened 2 years ago
Hum, it looks like it's in Python tokenize itself:
In [2]: %%timeit
...: buf.seek(0)
...: list(generate_tokens(buf.readline))
7.46 s ± 25.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
The chain dependency is long ipython->stack_data->executing->asttokens->python's generate_token, but it seem to be called greedily, i'll see if I can make lazy, or optimized.
I can potentially see another place that is slow, and that would be easier to improve for complex ast trees which might be a better read world example.
@alexmojaki I've tracked that down to a few things (depending of the type of files you try it on):
mark_tokens
functions that is greedily called in ASTTokens's contructors, _expand_to_matching_pairs
, and in particular for tok in self._code.token_range(first_token, last_token)
patched_generate_tokens(original_tokens)
, but it's own timing seem to often be the tokenize module of CPython being slow. I'll see if I can com up with improvements, but I thought it might be of interest, and maybe you have better ideas as to whether mark_tokens
can be made lazy maybe?
I actually think the way forward is to stop using asttokens in stack_data for Python >= 3.8. All that's needed is the range of source positions. It's not quite as simple as ast.get_source_segment
, but it's close.
Sorry for not replying sooner :disappointed: But optimisations in asttokens are still appreciated :pray:
No worries, If you have thoughts or another issue, I can have a look and try to implement it.
@Carreau see link above
As another option, would it be possible to add an opt-out flag somewhere that would save most of this time?
This was part of a large refactor for 8.0 and would be quite hard to put behind a flag, I'll look into the link that @alexmojaki posted and see what difference this makes. I've also seen tokenize perf improvement on Python 3.11 that should also speedup tracebacks.
@Carreau you don't have to actually do anything, I just thought I should keep you in the loop a bit. There's still work to do that will take a bit of time, but it should all be within stack_data and asttokens and not require any changes in IPython. The result should be no tokenizing being done at all.
I can definitely imagine a flag which switches to entirely plain traces using the standard traceback
module still being useful sometimes for various reasons.
Finally done! pip install -U asttokens
. For me, it's more than twice as fast as before.
IPython 8's tracebacks are much slower than IPython 7's for large files.
Reproducer:
IPython 8.4.0:
IPython 7.34.0:
Can this be fixed (aside from making our files smaller)? We have seen these slow tracebacks in some larger real world modules due to their file size (e.g. Pandas.Seriesis 6.4k LOC).