-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add middleware to record YJIT code_region_size (#53)
* Add middleware to record yjit code_region_size * We are using the rack.after_reply hook for this to not impact response times - https://github.blog/2022-04-11-performance-at-github-deferring-stats-with-rack-after_reply/ * Just a simple implimentation now, so we can optimise --yjit-exec-mem-size on applications, but this should be simple to extend to record the other metrics exposed by runtime_stats if they are needed. * Test behaviour with and without yjit enabled
- Loading branch information
Showing
5 changed files
with
72 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
require "promenade/yjit/stats" | ||
|
||
module Promenade | ||
module YJIT | ||
class Middlware | ||
RACK_AFTER_REPLY = "rack.after_reply".freeze | ||
|
||
def initialize(app) | ||
@app = app | ||
end | ||
|
||
def call(env) | ||
if env.key?(RACK_AFTER_REPLY) | ||
env[RACK_AFTER_REPLY] << -> { | ||
::Promenade::YJIT::Stats.instrument | ||
} | ||
end | ||
@app.call(env) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
module Promenade | ||
module YJIT | ||
class Stats | ||
Promenade.gauge :ruby_yjit_code_region_size do | ||
doc "Ruby YJIT code size" | ||
end | ||
|
||
def self.instrument | ||
return unless defined?(::RubyVM::YJIT) && ::RubyVM::YJIT.enabled? | ||
|
||
Promenade.metric(:ruby_yjit_code_region_size).set({}, ::RubyVM::YJIT.runtime_stats[:code_region_size]) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
require "promenade/yjit/stats" | ||
|
||
RSpec.describe Promenade::YJIT::Stats do | ||
describe "recording yjit stats" do | ||
it "records code_region_size" do | ||
# This method should not blow up in any case | ||
expect { described_class.instrument }.not_to raise_error | ||
|
||
if defined?(RubyVM::YJIT) && defined?(RubyVM::YJIT.enable) | ||
|
||
# We want to test that this doesn't blow up when yjit is present but isn't enabled yet | ||
# you need to run the testsuite with yjit disabled for this to work | ||
expect(RubyVM::YJIT.enabled?).to be_falsey | ||
expect { described_class.instrument }.not_to raise_error | ||
|
||
# Then we enable yjit to test the instrumentation | ||
RubyVM::YJIT.enable | ||
described_class.instrument | ||
|
||
expect(Promenade.metric(:ruby_yjit_code_region_size).get).to eq RubyVM::YJIT.runtime_stats[:code_region_size] | ||
else | ||
version = RUBY_VERSION.match(/(\d).(\d).\d/) | ||
major = version[1].to_i | ||
minor = version[2].to_i | ||
if major >= 3 && minor >= 3 | ||
flunk "YJIT must be avalibe to test properly in ruby 3.3+" | ||
end | ||
end | ||
end | ||
end | ||
end |