asyncrun.vim
asyncrun.vim copied to clipboard
Utilize autoload-functions to speed up Vim start-up
And it's preferable to only keep user interface codes in plugin/.
asyncrun is not complex now (966 lines). A lot of plugins are written in a single file (fugitive/3000 lines, taglist/4700 lines) if the loc exceeds 1000, I 'd like to move it to autoload. before that, let's keep it as a lightweight and single source file plugin ?
That depends on the frequency of one's utilization of a plugin. If yet I only occasionally use this plugin, I want to pay as little as possible as I would have a lot of occasionally used plugins. As for fugitive, it may load much of its functionality upon editing the first file. Thus the gain would be negligible if functions are autoloaded.
You can move asyncrun.vim to your autoload as well.
and put two lines below in your .vimrc:
command! -bang -nargs=+ -complete=file AsyncRun call asyncrun#run('<bang>', '', <q-args>)
command! -bang -nargs=0 AsyncStop call asyncrun#stop('<bang>')
@skywind3000 This sounds easy to do. Why do you not want to do this?
Tagbar (maintained alternative to taglist) has only 152 lines in plugin/ and 3389 lines in autoload/.
I am actually not happy about fugitive either but this is not a reason not doing if it is possible as in your case.
Also your code size has increased to 1477 lines (1366 sloc).
Comparing asyncrun.vim with plugins targeting similar functionality
- https://github.com/hauleth/asyncdo.vim/blob/master/plugin/asyncdo.vim 15 sloc
- https://github.com/yegappan/asyncmake/blob/master/plugin/asyncmake.vim 25 sloc
- https://github.com/pgdouyon/vim-accio/blob/master/plugin/accio.vim 37 sloc (50 stars)
- https://github.com/tpope/vim-dispatch/blob/master/plugin/dispatch.vim 66 sloc (1800 stars)
- https://github.com/neomake/neomake/blob/master/plugin/neomake.vim 103 sloc (1900 stars)
It is never a problem, use this: https://github.com/junegunn/vim-plug as your package manager.
vim-plug will load plugins on demand (only load this plugin when command :AsyncRun is invoked).
I was pinging this issue because you had written
if the loc exceeds 1000, I'd like to move it to autoload.
and this now the case.
I do not use vim-plug but minpac. Enforcing user to use a certain plugin manager is not really user-friendly and I think not the vim way. I would hope that you can acknowlege that people have different preferences regarding plugins and plugin manager as well. vim8 has even added the package feature which allows people to stay away from all plugin manager.
Following the officially recommended way to handle this is much more advisable.
I use a plugin-heavy vim setup and virtually all plugins use the recommended way of organizing code into plugin/ and autoload/ files.
There is a dedicated vim help page to quickload a plugin and this recommends for vim 7 and later to use autoload functionality :h write-plugin-quickload:
Note that since Vim 7 there is an alternative: use the |autoload| functionality |41.15|.
vim help for autoload:
:h autoload-functions Using an autoload script
Also the ebook Learn Vimscript the Hard Way has dedicated a chapter for this:
Chapter 53 Autoloading http://learnvimscriptthehardway.stevelosh.com/chapters/53.html
[...], if you're creating a plugin that won't be used every time a user opens a Vim session it's probably a good idea to move as much functionality into autoloaded files as possible. This will reduce the impact your plugin has on your users' startup times, which is important as people install more and more Vim plugins.
So what kind of things can be safely autoloaded? The answer is basically anything that's not directly called by your users.
IMHO this would also improve the perceived quality of your plugin.
I hope I could convince you to still do this: not necessarily in the next week but maybe in the next quarter or so.
Create a git branch for this change, make a first version and let it age a while. vim-dispatch has a branch for vim8 job control created some time ago, and eventually will become part of vim-dispatch. I think this is a feasible route to go. People can try this branch and report issues. You do not annoy people who prefer a stable plugin and do not want to be bothered by first baby issues.
All I have written has only the intention to improve asyncrun.vim not to get on your nerves 😅.
Normally I'd agree with @bohrshaw and @kiryph, but testing asyncrun.vim using vim --startuptime only leads to <1-2 milisecond additional load time, which is fine in my opinion. Negligible gains would be had from moving to autoload. At least, that is the case for my setup on various machines.
The startup time is usually fine nowadays because of the SSD (and most other plugins utilizing "autoload"). For old PCs, the worst case is a cold load from an HDD.
Regarding the worth of performance optimization: The startup performance is actually less important than runtime performance.
(and most other plugins utilizing "autoload")
luckily they are doing it. Isn't this an indication that one should do it? If no plugin would do it, maybe this discussion would be different.
And by the way not every remote machine has switched to SSD.
IMHO, it looks like one or two years ago it would not have been a big deal, but now it is. I think D. Knuths advice is not always the best (premature optimization is the root of all evil). Planning a little bit ahead and give your plugin a little bit of space to grow in size and functionality is not a bad thing. Some day you reach a state where such a change is more complicated and no one wants to do it. Other reasons are: organized code is easier to manage, following common practice makes it easier for others to find quicker things (mappings, commands and required initialization in plugin/... and everything else is in autoload).
I also did a measurement on my system. ~~Apparently my SSD is not as quick as yours. For me it is additional 9ms startup time:~~
UPDATE
Sorry, I just had a look into the option --clean and this disables also the builtin plugins.
A second measurement reveals for a startup with default plugins but no asyncrun.vim a startup time of 35.216 +/- 1.77252. This means it is also for me only 2.5ms more with asyncrun.vim (37.7472 +/- 1.79596). So I guess now I could argue that premature optimization is the root of all evil 😄 .
Minimal Config
~/.vim-configs/mwe-asyncrun.vim
❯ tree
.
├── pack
│ └── manual
│ └── start
│ └── asyncrun.vim
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ │ ├── asyncrun.txt
│ │ ├── cooperate_with_fugitive.gif
│ │ ├── errormarker.jpg
│ │ └── screenshot.gif
│ └── plugin
│ └── asyncrun.vim
└── vimrc
6 directories, 8 files
~/.vim-configs/mwe-asyncrun.vim
❯ cat vimrc
runtime defaults.vim
~/.vim-configs/mwe-asyncrun.vim
❯ ln -snf ~/.vim-configs/mwe-asyncrun.vim ~/.vim
~/.vim-configs/mwe-asyncrun.vim
❯ ls -l ~/.vim
lrwxr-xr-x 1 kiryph staff 43 Apr 10 17:55 /Users/kiryph/.vim -> /Users/kiryph/.vim-configs/mwe-asyncrun.vim
Measurement (200 runs)
--clean
~/.vim-configs/mwe-asyncrun.vim
❯ for i in {1..200}; do vim --clean --startuptime vim-clean-startup-$i.log -c ":q"; done
~/.vim-configs/mwe-asyncrun.vim 11s
❯ tail -q -n 1 vim-clean-startup-*.log | awk '{ x+= $1; y+= $1^2; n++ } END { if (n > 0) print x / n,
sqrt(y/n-(x/n)^2);}'
28.1753 1.28384
The last line prints the average startup time in ms (here ~28.2ms) and the standard deviation (~1.3ms).
With asyncrun.vim
~/.vim-configs/mwe-asyncrun.vim
❯ for i in {1..200}; do vim --startuptime vim-startup-$i.log -c ":q"; done
~/.vim-configs/mwe-asyncrun.vim 13s
❯ tail -q -n 1 vim-startup-*.log | awk '{ x+= $1; y+= $1^2; n++ } END { if (n > 0) print x / n,
sqrt(y/n-(x/n)^2);}'
37.7472 1.79596
As you can see, I am not at 37.7ms +/- 1.8ms. ~~This is certainly more than other plugins such as dispatch, asyncmake, or neomake.~~
I totally agree with @bohrshaw and @kiryph either, I hesitated for one thing, through github searching, a lot users just drop the single file asyncrun.vim into their dotfiles repository as a basic component which can be used directly without installing from some plugin manager.
split into multiple files will break this.
Then they would add a directory to &rtp.
With vim8 you do not need a plugin manager, you do not need to touch your vimrc and installation is a one-liner:
$ git clone https://github.com/skywind3000/asyncrun.vim ~/.vim/pack/manual/start/asyncrun.vim
This will get the doc file as well which I would strongly recommend to install. vimhelp is certainly something where vim shines, keeping undocumented plugins in your dot repository would be again non advisable. You can see all doc files of your plugins under :h local-additions. Some people can get quite annoyed when people raise issues on github about something which has been explained in the doc file or ignoring a section called faq.
Adding an autoload dir does not look too difficult. This is something they do only once, typing vim into the shell is something which is done uncountable often.
I think the reason split into multiple files will break this for not doing it is rather weak.
However, I have to admit that presumably saving 1ms-2ms of startup time is not very much. On the other side if I have 50 plugins installed and all of them would reduce 1-2ms startup time, I would argue that wouldn't be too bad. Having plugins with almost no startup time will make people to keep a plugin even if they haven't made their decision whether they want to use it or not.
FYI: fugitive has recently moved most of the code to the autoload directory (see commit https://github.com/tpope/vim-fugitive/commit/5d11ff75014818da25596a89cea71df680e31788, 2018-06-01) with now following line counts: plugin/fugitive.vim: 190 lines (174 sloc) autoload/fugitive.vim: 3282 lines (3016 sloc)
A lot of plugins are written in a single file (fugitive/3000 lines, taglist/4700 lines)
does not hold for the plugins I use. BTW taglist is unmaintained.
agree
同意,plugin目录的脚本超过100行(除非这100行都是变量初始化),都建议做成autoload 我的插件都几十个了,启动超慢,现在得慢慢搞那些插件
Agree, it would be better to move implementation in autoload.
Now it's 2000 lines. I think you should consider it.