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

RBS::Prototype::Runtime#block_from_ast_of is dominant in terms of execution time. #1565

Open
ksss opened this issue Oct 12, 2023 · 0 comments

Comments

@ksss
Copy link
Collaborator

ksss commented Oct 12, 2023

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant