ruby/tool/zjit_analyze_perf_map_size.rb
Max Bernstein 1d363d6f41
ZJIT: Add small tool to analyze perf map (#17734)
It tells you total size per symbol, average size per instance of symbol,
and total count per symbol.

Can be used with `--zjit-perf=hir`:

```
plum% ruby ../tool/zjit_analyze_perf_map_size.rb /tmp/perf-16653.map
12.1 MB total; 277.5 B each side-exit
2.2 MB total; 16.9 B each PatchPoint
2.1 MB total; 197.4 B each SendDirect
1.3 MB total; 10.7 B each PadPatchPoint
973.6 KB total; 56.5 B each GuardType
952.6 KB total; 97.7 B each HasType
910.4 KB total; 111.2 B each Send
705.0 KB total; 218.0 B each CCallWithFrame
689.9 KB total; 149.0 B each PushInlineFrame
559.8 KB total; 247.5 B each CCallVariadic
440.4 KB total; 32.0 B each EntryPoint
387.9 KB total; 17.8 B each CheckInterrupts
356.8 KB total; 66.7 B each GetIvar
326.3 KB total; 11.0 B each Jump
198.2 KB total; 8.0 B each CondBranch
167.6 KB total; 22.3 B each Return
163.5 KB total; 4.8 B each LoadField
149.0 KB total; 23.6 B each IsBitEqual
142.4 KB total; 100.0 B each HashAref
135.9 KB total; 16.3 B each Test

138705 PatchPoint
128879 PadPatchPoint
124942 Snapshot
45884 side-exit
40535 Const
34701 LoadField
30364 Jump
25234 CondBranch
22264 CheckInterrupts
17657 GuardType
16101 LoadArg
14081 EntryPoint
12892 RefineType
11106 SendDirect
9980 HasType
8541 Test
8385 Send
7693 Return
6938 GuardBitEquals
6699 LoadSelf
plum%
```

or with just `--zjit-perf`:

```
plum% ruby ../tool/zjit_analyze_perf_map_size.rb /tmp/perf-22517.map
770.7 KB total; 192.7 KB each _app_views_stories__listdetail_html_erb__2872691580871714137_14696@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/stories/_listdetail.html.erb:1
452.0 KB total; 150.7 KB each _app_views_layouts_application_html_erb__3422508349557286544_14376@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/layouts/application.html.erb:1
232.9 KB total; 232.9 KB each _app_views_comments__comment_html_erb___3513273811879470227_16232@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/comments/_comment.html.erb:1
200.9 KB total; 50.2 KB each block-in initialize@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/erubi-1.13.1/lib/erubi.rb:135
194.0 KB total; 64.7 KB each parse@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/tzinfo-2.0.6/lib/tzinfo/data_sources/zoneinfo_reader.rb:345
191.8 KB total; 191.8 KB each _app_views_comments__comment_html_erb___3513273811879470227_15016@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/comments/_comment.html.erb:1
167.4 KB total; 167.4 KB each _app_views_comments__comment_html_erb___3513273811879470227_16488@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/comments/_comment.html.erb:1
165.9 KB total; 165.9 KB each _app_views_stories__listdetail_html_erb__2872691580871714137_15008@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/stories/_listdetail.html.erb:1
124.3 KB total; 31.1 KB each build_arel@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/query_methods.rb:1751
120.9 KB total; 30.2 KB each _delegator_method@/Users/emacs/.rubies/ruby-zjit-rel-stats/lib/ruby/4.1.0+4/forwardable.rb:202
119.5 KB total; 29.9 KB each perform_query@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/connection_adapters/sqlite3/database_statements.rb:87
111.6 KB total; 55.8 KB each _app_views_stories_show_html_erb__2313005407901203172_15000@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/stories/show.html.erb:1
103.8 KB total; 25.9 KB each block-in generate@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activesupport-8.1.1/lib/active_support/delegation.rb:72
98.3 KB total; 98.3 KB each _app_views_users_show_html_erb___3973630128665404112_14592@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/users/show.html.erb:1
91.0 KB total; 45.5 KB each normalize_options@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/dsl.rb:394
85.9 KB total; 21.5 KB each parse@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/tzinfo-2.0.6/lib/tzinfo/data_sources/posix_time_zone_parser.rb:37
74.5 KB total; 37.3 KB each generate@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activesupport-8.1.1/lib/active_support/delegation.rb:22
69.0 KB total; 17.3 KB each determine_template@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionview-8.1.1/lib/action_view/renderer/template_renderer.rb:17
67.5 KB total; 16.9 KB each block-in expand_from_hash@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/predicate_builder.rb:88
65.2 KB total; 16.3 KB each block-in derive_offsets@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/tzinfo-2.0.6/lib/tzinfo/data_sources/zoneinfo_reader.rb:118

17 __callbacks@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activesupport-8.1.1/lib/active_support/callbacks.rb:70
12 _layout@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionview-8.1.1/lib/action_view/layouts.rb:329
5 __callbacks=@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activesupport-8.1.1/lib/active_support/callbacks.rb:70
5 default_url_options@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionpack-8.1.1/lib/action_dispatch/routing/url_for.rb:100
4 scope@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/associations/association.rb:108
4 default_render@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionpack-8.1.1/lib/action_controller/metal/implicit_render.rb:38
4 scope@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/associations/association_scope.rb:22
4 get_method_for_class@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionpack-8.1.1/lib/action_dispatch/routing/polymorphic_routes.rb:348
4 visit_Arel_Nodes_SqlLiteral@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/arel/visitors/to_sql.rb:755
4 block-in preprocess_order_args@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/query_methods.rb:2105
4 strictly_lower?@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb:179
4 choose_compatible@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/lazy_specification.rb:236
4 column_types@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/result.rb:168
4 local_search@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/index.rb:65
4 method_defined_within?@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/attribute_methods.rb:187
4 join_scopes@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/reflection.rb:227
4 block-in expand_from_hash@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/predicate_builder.rb:88
4 block-in convert_dot_notation_to_hash@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/predicate_builder.rb:166
4 block-in references@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/predicate_builder.rb:29
4 block-in materialize_dependencies@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/spec_set.rb:246
plum%
```
2026-07-14 13:02:19 -04:00

41 lines
1008 B
Ruby
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env ruby
required_ruby_version = Gem::Version.new("3.4.0")
raise "Ruby version #{required_ruby_version} or higher is required" if Gem::Version.new(RUBY_VERSION) < required_ruby_version
PERF_MAP = ARGV[0] || raise("Expected perf map as first argument")
sizes = Hash.new(0)
counts = Hash.new(0)
File.foreach(PERF_MAP) do |line|
address, size, name = line.split(" ", 3)
name.delete_prefix!("ZJIT: ")
name.delete_suffix!("\n")
sizes[name] += size.to_i(16)
counts[name] += 1
end
total_size = sizes.values.sum
def pretty_size bytes
u = 0
s = 1024
while bytes >= s || -bytes >= s
bytes /= s.to_f
u += 1
end
"#{bytes.round(1)} #{'KMGTPEZY'[u]}B"
end
n = 20
sizes.sort_by { |name, size| -size }.first(n).each do |name, size|
puts "#{pretty_size(size)} total (#{(size/total_size.to_f*100).round(1)}%); #{pretty_size(size/counts[name].to_f)} each #{name}"
end
puts
counts.sort_by { |name, count| -count }.first(n).each do |name, count|
puts "#{count} #{name}"
end