Skip to content
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

Improve evaluation experience for large values #376

Merged
merged 3 commits into from
Dec 21, 2021

Conversation

Cnly
Copy link
Contributor

@Cnly Cnly commented Dec 19, 2021

The other day I had a cider-nrepl server started inside a project that doesn't have iced-nrepl in it. When I :IcedConnect to it, it sent back a 1,201,722-byte bencoded string (I'm not familiar with the nrepl protocol so have no idea what it is; it began with a d18:changed-namespaces dict) which froze my nvim for 79 seconds... that's a throughput of 15KB/s and sounds a bit too slow. Profiling shows:

FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
   10  78.780231  78.630764  provider#python3#Call()
    8             78.627463  <SNR>292_decode_via_python()
    327019 function calls (255933 primitive calls) in 70.975 seconds

    Ordered by: standard name
 
    ncalls  tottime  percall  cumtime  percall filename:lineno(function)
         1    0.000    0.000    0.000    0.000 _bootlocale.py:33(getpreferredencoding)
         1    0.000    0.000    0.000    0.000 bencode.py:18(__decode_integer)
         1    0.000    0.000    0.000    0.000 bencode.py:29(__decode_list)
         1    0.004    0.004   70.975   70.975 bencode.py:3(<module>)
     51182   13.666    0.000   61.401    0.001 bencode.py:3(__decode_string)
    9952/1    7.920    0.001   70.969   70.969 bencode.py:46(__decode_dict)
   61136/1    1.647    0.000   70.969   70.969 bencode.py:62(__decode)
         1    0.000    0.000   70.969   70.969 bencode.py:75(iced_bencode_decode)
         1    0.000    0.000    0.000    0.000 codecs.py:260(__init__)
         1    0.000    0.000    0.000    0.000 codecs.py:309(__init__)
         1    0.000    0.000    0.002    0.002 codecs.py:319(decode)
         1    0.002    0.002    0.002    0.002 {built-in method _codecs.utf_8_decode}
         1    0.000    0.000    0.000    0.000 {built-in method _locale.nl_langinfo}
         1    0.000    0.000   70.975   70.975 {built-in method builtins.exec}
         2    0.000    0.000    0.000    0.000 {built-in method builtins.len}
         1    0.000    0.000    0.000    0.000 {built-in method builtins.print}
         1    0.000    0.000    0.000    0.000 {built-in method io.open}
         1    0.000    0.000    0.000    0.000 {method '__exit__' of '_io._IOBase' objects}
         2    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
    102364   14.094    0.000   14.094    0.000 {method 'decode' of 'bytes' objects}
         1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     51182   33.599    0.001   33.599    0.001 {method 'encode' of 'str' objects}
     51183    0.043    0.000    0.043    0.000 {method 'find' of 'str' objects}
         1    0.001    0.001    0.003    0.003 {method 'read' of '_io.TextIOWrapper' objects}

So this PR improves that by

  • Reducing the excessive number of calls to .encode() and .decode().
  • Avoiding creating new strings by slicing on every return.

Profiling after the changes:

FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
   10   3.374407   3.205914  provider#python3#Call()
    8              3.203132  <SNR>292_decode_via_python()
         326315 function calls (255229 primitive calls) in 0.140 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 _bootlocale.py:33(getpreferredencoding)
        1    0.000    0.000    0.000    0.000 bencode.py:16(__decode_integer)
        1    0.000    0.000    0.000    0.000 bencode.py:26(__decode_list)
        1    0.001    0.001    0.140    0.140 bencode.py:3(<module>)
    51182    0.049    0.000    0.073    0.000 bencode.py:3(__decode_string)
   9952/1    0.027    0.000    0.135    0.135 bencode.py:43(__decode_dict)
  61136/1    0.028    0.000    0.135    0.135 bencode.py:59(__decode)
        1    0.000    0.000    0.136    0.136 bencode.py:71(iced_bencode_decode)
        1    0.000    0.000    0.000    0.000 codecs.py:260(__init__)
        1    0.000    0.000    0.000    0.000 codecs.py:309(__init__)
        1    0.000    0.000    0.001    0.001 codecs.py:319(decode)
        1    0.001    0.001    0.001    0.001 {built-in method _codecs.utf_8_decode}
        1    0.000    0.000    0.000    0.000 {built-in method _locale.nl_langinfo}
   101657    0.008    0.000    0.008    0.000 {built-in method builtins.chr}
        1    0.000    0.000    0.140    0.140 {built-in method builtins.exec}
        4    0.000    0.000    0.000    0.000 {built-in method builtins.len}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        1    0.000    0.000    0.000    0.000 {built-in method io.open}
        1    0.000    0.000    0.000    0.000 {method '__exit__' of '_io._IOBase' objects}
        2    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
    51182    0.011    0.000    0.011    0.000 {method 'decode' of 'bytes' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.001    0.001    0.001    0.001 {method 'encode' of 'str' objects}
    51183    0.012    0.000    0.012    0.000 {method 'find' of 'bytes' objects}
        1    0.001    0.001    0.003    0.003 {method 'read' of '_io.TextIOWrapper' objects}

which is ~500x improvement. The code does look a little bit harder to deal with than before, but I still hope this can be useful to iced.

@liquidz
Copy link
Owner

liquidz commented Dec 19, 2021

@Cnly Thanks!
I'll have a look tomorrow.

When I :IcedConnect to it, it sent back a 1,201,722-byte bencoded string

The cause may be track-state middleware.
#170

which is ~500x improvement.

Wow, awesome!

Copy link
Owner

@liquidz liquidz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Cnly Thanks for your contribution!
Overall the PR looks good.
Could you add only tests I commented on?

python/bencode.py Show resolved Hide resolved
python/bencode.py Outdated Show resolved Hide resolved
@Cnly
Copy link
Contributor Author

Cnly commented Dec 21, 2021

Not sure if the version problem is something we want to fix in this PR. Maybe not?

Copy link
Owner

@liquidz liquidz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Cnly Great work! Thanks!

@liquidz
Copy link
Owner

liquidz commented Dec 21, 2021

Not sure if the version problem is something we want to fix in this PR. Maybe not?

This may result in a solution, but the Vim script version is still slow and not fixed.
https://github.com/liquidz/vim-iced/blob/300552623923cbda4918f3b7c1bea41dae63008a/autoload/iced/component/bencode/vim.vim

Anyway, thank you so much for your work!

@liquidz liquidz merged commit 383705f into liquidz:main Dec 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants