`RBS::Prototype::Runtime#block_from_ast_of` is dominant in terms of execution time.
Opened this issue · 0 comments
Most of the execution time in rbs prototype runtime
is taken up by RBS::Prototype::Runtime#block_from_ast_of
.
This means that a significant amount of cost is being spent just to investigate whether a method's block is mandatory or not.
For example, when running rbs prototype runtime
targeting ActiveSupport::*
, 65% of the time is spent on this process.
The behavior of RBS::Prototype::Runtime#block_from_ast_of
is not perfect, as I pointed out in #1180 (comment), and I believe a perfect judgment is fundamentally very difficult.
I feel that the use of rbs prototype runtime
is being avoided due to its slow execution time.
Almost all of the execution time for RBS::Prototype::Runtime#block_from_ast_of
comes from RubyVM::AbstractSyntaxTree.of
, and there's no room for optimization.
I propose that rbs prototype runtime
block arguments should always be considered optional.
Benchmark script
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'activesupport'
gem 'stackprof'
end
require 'active_support/all'
ActiveSupport.eager_load!
$LOAD_PATH.unshift << File.expand_path("../lib", __dir__)
require 'rbs'
env = RBS::Environment.from_loader(RBS::EnvironmentLoader.new).resolve_type_names
StackProf.run(mode: :wall, out: "stackprof-wall.dump", interval: 100) do
RBS::Prototype::Runtime.new(
patterns: ["ActiveSupport::*"],
env: env,
merge: false,
todo: false,
owners_included: []
).decls
end
$ bundle exec stackprof stackprof-wall.dump
==================================
Mode: wall(100)
Samples: 2959 (16.22% miss rate)
GC: 519 (17.54%)
==================================
TOTAL (pct) SAMPLES (pct) FRAME
1927 (65.1%) 1925 (65.1%) RubyVM::AbstractSyntaxTree.of
339 (11.5%) 339 (11.5%) (sweeping)
266 (9.0%) 266 (9.0%) (marking)
33 (1.1%) 29 (1.0%) Kernel#require
2261 (76.4%) 24 (0.8%) RBS::Prototype::Runtime#generate_methods
41 (1.4%) 24 (0.8%) Class#new
69 (2.3%) 18 (0.6%) RBS::Prototype::Helpers#each_node
17 (0.6%) 17 (0.6%) RubyVM::AbstractSyntaxTree::Node#type
15 (0.5%) 15 (0.5%) Module#public_instance_methods
71 (2.4%) 15 (0.5%) RBS::Prototype::Helpers#any_node?
48 (1.6%) 15 (0.5%) Module#const_get
14 (0.5%) 14 (0.5%) Module#private_instance_methods
14 (0.5%) 14 (0.5%) String#split
14 (0.5%) 14 (0.5%) Module#instance_method
14 (0.5%) 14 (0.5%) String#inspect
13 (0.4%) 13 (0.4%) RubyVM::AbstractSyntaxTree::Node#children
2126 (71.8%) 12 (0.4%) RBS::Prototype::Runtime#method_type
32 (1.1%) 10 (0.3%) RBS::Prototype::Runtime#each_mixined_module_one
23 (0.8%) 9 (0.3%) Array#inspect
13 (0.4%) 9 (0.3%) RBS::Prototype::Runtime#ensure_outer_module_declarations
24 (0.8%) 8 (0.3%) RBS::Prototype::Runtime#target_method?
37 (1.3%) 8 (0.3%) Array#select
79 (2.7%) 7 (0.2%) RBS::Prototype::Helpers#block_from_body
28 (0.9%) 7 (0.2%) RBS::Prototype::Runtime#const_name
5 (0.2%) 5 (0.2%) UnboundMethod#parameters
5 (0.2%) 5 (0.2%) Symbol#match?
5 (0.2%) 4 (0.1%) Array#sort
2399 (81.1%) 4 (0.1%) Array#each
69 (2.3%) 4 (0.1%) RBS::Prototype::Helpers#each_child
3 (0.1%) 3 (0.1%) Kernel#singleton_class
$ bundle exec stackprof --method RubyVM::AbstractSyntaxTree.of stackprof-wall.dump
RubyVM::AbstractSyntaxTree.of (<internal:ast>:96)
samples: 1925 self (65.1%) / 1927 total (65.1%)
callers:
1927 ( 100.0%) RBS::Prototype::Runtime#block_from_ast_of
callees (2 total):
2 ( 100.0%) Exception#initialize
code:
SOURCE UNAVAILABLE