98 lines
2.7 KiB
Ruby
98 lines
2.7 KiB
Ruby
|
#!/usr/bin/env ruby
|
||
|
# frozen_string_literal: true
|
||
|
|
||
|
####
|
||
|
# Loads GitLab application classes with a variety of GC settings and prints
|
||
|
# GC stats and timing data to standard out as CSV.
|
||
|
#
|
||
|
# The degree of parallelism can be increased by setting the PAR environment
|
||
|
# variable (default: 2).
|
||
|
|
||
|
require 'benchmark'
|
||
|
|
||
|
SETTINGS = {
|
||
|
'DEFAULTS' => [''],
|
||
|
# Default: 10_000
|
||
|
'RUBY_GC_HEAP_INIT_SLOTS' => %w[100000 1000000 5000000],
|
||
|
# Default: 1.8
|
||
|
'RUBY_GC_HEAP_GROWTH_FACTOR' => %w[1.2 1 0.8],
|
||
|
# Default: 0 (disabled)
|
||
|
'RUBY_GC_HEAP_GROWTH_MAX_SLOTS' => %w[10000 100000 1000000],
|
||
|
# Default: 2.0
|
||
|
'RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR' => %w[2.5 1.5 1],
|
||
|
# Default: 4096 (= 2^12)
|
||
|
'RUBY_GC_HEAP_FREE_SLOTS' => %w[16384 2048 0],
|
||
|
# Default: 0.20 (20%)
|
||
|
'RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO' => %w[0.1 0.01 0.001],
|
||
|
# Default: 0.40 (40%)
|
||
|
'RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO' => %w[0.2 0.01 0.001],
|
||
|
# Default: 0.65 (65%)
|
||
|
'RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO' => %w[0.2 0.02 0.002],
|
||
|
# Default: 16MB
|
||
|
'RUBY_GC_MALLOC_LIMIT' => %w[8388608 4194304 1048576],
|
||
|
# Default: 32MB
|
||
|
'RUBY_GC_MALLOC_LIMIT_MAX' => %w[16777216 8388608 1048576],
|
||
|
# Default: 1.4
|
||
|
'RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR' => %w[1.6 1 0.8],
|
||
|
# Default: 16MB
|
||
|
'RUBY_GC_OLDMALLOC_LIMIT' => %w[8388608 4194304 1048576],
|
||
|
# Default: 128MB
|
||
|
'RUBY_GC_OLDMALLOC_LIMIT_MAX' => %w[33554432 16777216 1048576],
|
||
|
# Default: 1.2
|
||
|
'RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR' => %w[1.4 1 0.8]
|
||
|
}.freeze
|
||
|
|
||
|
USED_GCSTAT_KEYS = [
|
||
|
:minor_gc_count,
|
||
|
:major_gc_count,
|
||
|
:heap_live_slots,
|
||
|
:heap_free_slots,
|
||
|
:total_allocated_pages,
|
||
|
:total_freed_pages,
|
||
|
:malloc_increase_bytes,
|
||
|
:malloc_increase_bytes_limit,
|
||
|
:oldmalloc_increase_bytes,
|
||
|
:oldmalloc_increase_bytes_limit
|
||
|
].freeze
|
||
|
|
||
|
CSV_USED_GCSTAT_KEYS = USED_GCSTAT_KEYS.join(',')
|
||
|
CSV_HEADER = "setting,value,#{CSV_USED_GCSTAT_KEYS},RSS,gc_time_s,cpu_utime_s,cpu_stime_s,real_time_s\n"
|
||
|
|
||
|
SCRIPT_PATH = __dir__
|
||
|
RAILS_ROOT = "#{SCRIPT_PATH}/../../../"
|
||
|
|
||
|
def collect_stats(setting, value)
|
||
|
warn "Testing #{setting} = #{value} ..."
|
||
|
env = {
|
||
|
setting => value,
|
||
|
'RAILS_ROOT' => RAILS_ROOT,
|
||
|
'SETTING_CSV' => "#{setting},#{value}",
|
||
|
'GC_STAT_KEYS' => CSV_USED_GCSTAT_KEYS
|
||
|
}
|
||
|
system(env, 'ruby', "#{SCRIPT_PATH}/print_gc_stats.rb")
|
||
|
end
|
||
|
|
||
|
par = ENV['PAR']&.to_i || 2
|
||
|
batch_size = (SETTINGS.size.to_f / par).ceil
|
||
|
batches = SETTINGS.each_slice(batch_size)
|
||
|
|
||
|
warn "Requested parallelism: #{par} (batches: #{batches.size}, batch size: #{batch_size})"
|
||
|
|
||
|
puts CSV_HEADER
|
||
|
|
||
|
elapsed = Benchmark.realtime do
|
||
|
threads = batches.each_with_index.map do |settings_batch, n|
|
||
|
Thread.new do
|
||
|
settings_batch.each do |setting, values|
|
||
|
values.each do |v|
|
||
|
collect_stats(setting, v)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
threads.each(&:join)
|
||
|
end
|
||
|
|
||
|
warn "All done in #{elapsed} sec"
|