35

Performance profile · Issue #140 · liuchengxu/vim-clap · GitHub

 4 years ago
source link: https://github.com/liuchengxu/vim-clap/issues/140
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

To fix the performance issue, ensure you have Rust installed on your system and run :call clap#helper#build_all().


Introduction

The one selling point of vim-clap is in pure vimscript, having a good platform compatibility and minimal pain to set it up, which is apparently an advantage. However, it becomes a disadvantage when you do a large scale searching/filtering job for the limit of vimscript language.

Profile of async job at scale

For instance, using :Clap files from my home directory and input sr, the result is [791970/823172]. The following profile info is based on this commit dfffb5e.

Profile of NeoVim:

FUNCTIONS SORTED ON TOTAL TIME
count  total (s)   self (s)  function
16737   2.416528   0.592996  <SNR>181_on_event()
16732   1.816953   0.267504  <SNR>181_append_output()
16731   1.505205   0.146196  <SNR>181_set_matches_count()
16732   1.379571   0.310434  clap#impl#refresh_matches_count()
16732   0.821710   0.141712  clap#indicator#set_matches()
16732   0.679998   0.317742  <SNR>183_apply_indicator()
    3   0.492807   0.472198  <SNR>172_on_event()
16732   0.362257   0.177423  <SNR>183_padding()
16733   0.247077   0.140285  clap#sign#reset_to_first_line()
    8   0.195782             provider#python3#Call()
16740   0.184996   0.100084  16()
    5   0.147412             UltiSnips#TrackChange()
16732   0.106776             <SNR>184_sign_of_first_line()
16740   0.084913             clap#util#nvim_buf_get_first_line()
    3   0.078762   0.000110  clap#handler#on_typed()
    2   0.078562   0.003062  41()
    2   0.075139   0.000245  clap#impl#on_typed()
    5   0.067303   0.000438  clap#rooter#run()
    2   0.063340   0.004730  <SNR>179_on_typed_async_impl()
    2   0.052697   0.000056  clap#dispatcher#job_start()

Profile of Vim:

FUNCTIONS SORTED ON TOTAL TIME
count  total (s)   self (s)  function
1613221  70.847359  38.246657  <SNR>172_out_cb()
1613224  31.405335  18.249628  clap#job#vim8_job_id_of()
1613229  13.155912             clap#job#parse_vim8_job_id()
791899   1.191679             <SNR>172_handle_cache()
    1   0.537275   0.517298  <SNR>167_close_cb()
   61   0.183191   0.007911  ElelineGitBranch()
   60   0.170001   0.154896  FugitiveExtractGitDir()
   18   0.021677   0.001292  <SNR>162_popup_filter()
    2   0.020385   0.000444  142()
    3   0.020079   0.019061  clap#impl#refresh_matches_count()
    1   0.019937   0.000054  <SNR>167_on_complete()
    2   0.019428   0.000085  <SNR>162_apply_input()
    2   0.019320   0.001760  117()
    5   0.018673   0.001056  clap#rooter#run()
    2   0.016882   0.000210  clap#impl#on_typed()
   10   0.014478   0.003716  traces#init()
    2   0.014044   0.000092  <SNR>172_post_check()
    2   0.013604   0.000199  <SNR>172_on_exit_common()
    2   0.013177   0.000034  clap#impl#add_highlight_for_fuzzy_indices()
    2   0.013143   0.010832  <SNR>170_apply_add_highlight()

For the result set having about 1M items, neovim is still tolerable if you seldom run into that case, but for vim it's totally unusable. The core idea of vim-clap is to spawn a new job on your typing and then react on the callback, the callback of the job is called too many times on the surface.

Related providers

The performance issue only happens to these providers that can have a huge result set.

Searching

  • :Clap files
  • :Clap grep

Filtering

The current strategy is to use the built-in fzy written in python running synchronously when the items are no more than 10,000, switching the async way if it's more than the threshold and then it meets the same callback issue.

  • :Clap blines
  • :Clap lines
  • :Clap bcommits
  • :Clap commits

The challenge is to make clap#filter#() fast enough even when candidates is terrific.

function! clap#filter#(query, candidates) abort

Possible solution

  • python multi thread. Since we have introduced the optional dependency for the built-in fzy support, we could also use the thread of python to improve the performance as suggested in #75 (comment). As I'm not a python expert, I'm not sure if this will land in vim-clap eventually.

  • lua. Could be faster than vimscript at least in some filtering cases. I observe something promissing based on the this script measuring the vimscript with the other script languages:

    • lua is 4x faster than python.

    • luajit is 100x faster than python.

  • Boost python filtering using Rust. I'm interested if https://github.com/rochacbruno/rust-python-example would help, which can replace fuzzy_match():

    def fuzzy_match(query, candidates):
    The result shows that using Rust could be 10x faster, see #146, #147.
  • job

    • [-] Use a timer for reading the output of vim job periodly, then the callback won't be called that many times. This branch is my try with timer. Using a timer helps a lot, but some messages are dropped unexpected, not sure if that's bug of Vim or my code. I did not investigate further as I have achived the same goal with maple as follows.
    • Don't have to output all the fuzzy filtered items, we only show the top N candidates and care about the number of total candidates. The payload of async job will be significantly decreased if only these essential information is returned.(#181)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK