Understanding the performance of bin/logstash-plugin install command
- Dominant language
- Java
- Stars
- 14.9k
- Forks
- 3.5k
- Avg merge
- 19h 14m
- Merged PRs (30d)
- 63
Description
One of the common comments and concerns about logstash is it's performance, in this issue we try to understand the performance concerns involved in installing a plugin.
Here is a sample execution trying to install the generator input.
```
skywalker% JRUBY_OPTS="--profile" ./bin/logstash-plugin install logstash-input-generator
Profiling enabled; ^C shutdown will now dump profile info
Validating logstash-input-generator
Installing logstash-input-generator
Installation successful
main profile results:
Total time: 17.12
total self children calls method
----------------------------------------------------------------
15.18 0.00 15.18 1 Clamp::Command.run
15.18 0.00 15.18 2 Clamp::Command#run
15.18 0.00 15.18 1 Clamp::Subcommand::Execution.execute
15.18 0.00 15.18 1 LogStash::PluginManager::Install#execute
14.51 0.06 14.45 26035 Array#each
9.39 0.00 9.39 1 LogStash::PluginManager::Install#install_gems_list!
9.39 0.00 9.39 1 LogStash::Bundler.invoke!
9.27 0.00 9.27 5093 Proc#call
9.27 0.00 9.27 1 LogStash::Bundler.execute_bundler_with_retry
9.27 0.00 9.27 1 LogStash::Bundler.capture_stdout
9.27 0.00 9.27 1 Kernel.loop
9.27 0.00 9.27 1 LogStash::Bundler.execute_bundler
9.27 0.00 9.27 1 Bundler::CLI.start
9.27 0.00 9.27 1 Bundler::Thor::Base::ClassMethods.start
9.27 0.00 9.27 1 Bundler::Thor.dispatch
9.26 0.00 9.26 1 Bundler::Thor::Invocation.invoke_command
9.26 0.00 9.26 1 Bundler::Thor::Command#run
9.26 0.00 9.26 73 BasicObject#__send__
9.26 0.00 9.26 1 Bundler::CLI#install
9.26 0.00 9.25 1 Bundler::CLI::Install#run
9.15 0.00 9.15 1 Bundler::Installer.install
9.15 0.00 9.15 1 Bundler::Installer#run
8.29 0.00 8.29 1 Bundler::Installer#install_sequentially
7.64 0.00 7.64 72 Bundler::SpecSet#each
7.54 0.00 7.54 64 Bundler::Installer#install_gem_from_spec
7.51 0.00 7.51 3 Bundler::Source::Path#install
7.51 0.00 7.51 3 Bundler::Source::Path#generate_bin
7.38 0.00 7.38 6 Bundler::SharedHelpers.chdir
7.38 0.00 7.38 12 MonitorMixin.mon_synchronize
7.38 0.00 7.38 12 Dir.chdir
7.36 0.00 7.35 9 Bundler::Source::Path#run_hooks
7.33 0.00 7.33 3 Jars::Installer#vendor_jars
7.33 0.00 7.33 1 Jars::Installer#do_install
7.32 0.00 7.32 1 Jars::Installer#install_dependencies
7.32 0.00 7.32 1 Jars::MavenExec#resolve_dependencies_list
7.31 0.00 7.31 1 Maven::Ruby::Maven#exec
7.31 0.00 7.31 1 RubyMaven.exec
7.31 0.00 7.31 1 Bundler.with_clean_env
7.31 0.00 7.31 1 Bundler.with_original_env
7.31 0.00 7.31 1 RubyMaven.launch
7.30 0.00 7.30 1 Maven.exec
7.30 7.30 0.00 1 Kernel.system
5.78 0.00 5.78 1 LogStash::PluginManager::Install#verify_remote!
5.78 0.00 5.78 1 LogStash::PluginManager::Install#validate_plugin
5.78 0.00 5.78 1 LogStash::PluginManager.logstash_plugin?
5.57 0.00 5.57 1 Gem::SpecFetcher#spec_for_dependency
5.09 0.00 5.09 1 Gem::SpecFetcher#search_for_dependency
4.76 0.01 4.75 10790 Kernel.send
4.68 0.00 4.68 1 Gem::SpecFetcher#available_specs
4.68 0.00 4.68 1 Gem::SourceList#each_source
```
we can see how the biggest offenders in terms of execution time are:
- `LogStash::PluginManager.logstash_plugin?` taking 5.78s over a total of 17.12s what means a 33.76%
- `Bundler::Source::Path#run_hooks` basically the executions of `jar-dependencies` installation hook, this takes around another 34% of execution time, thinking of having a zero time logstash plugin validation.
Performance impact re the jvm looks around taking 1.94s of a total of 17.12s, so around 11%.
This two as the bigger offenders in terms of performance might be related to #4971 where @wiibaa shared the performance penalties of using `net::http`. Possible strategies I see so improve the performance of this command are:
- Upgrade current bundler version to the latest one, this might have some performance benefits and let us manage bottlenecks easier.
- Implement an improved version of `LogStash::PluginManager.logstash_plugin?`, probably using manticore as the fastest way do request stuff from the web.
- Let the jar-dependency hook only be run when it makes sense, see the profile is for the generator input that does not require any jar.
This will highly benefit:
- Our current testing infrastructure as we're running the plugin installation many times.
- The improvement on bundler and the post install hooks might help also the package build time.
- Even if it's not a common operation, the end user as it will have a faster installation command.
Contributor guide
Assessment
This issue has not been assessed yet.