Introduce support for dumping Rails process heap at the end of a benchmark run

This commit is contained in:
Lourens Naudé 2014-12-07 22:54:35 +00:00
parent c273a6d1d4
commit fb60daa867
4 changed files with 36 additions and 3 deletions

View file

@ -18,4 +18,20 @@ class Admin::DiagnosticsController < Admin::AdminController
content_type: Mime::TEXT content_type: Mime::TEXT
end end
def dump_heap
begin
# ruby 2.1
GC.start(full_mark: true)
require 'objspace'
io = File.open("discourse-heap-#{SecureRandom.hex(3)}.json",'w')
ObjectSpace.dump_all(:output => io)
io.close
render text: "HEAP DUMP:\n#{io.path}", content_type: Mime::TEXT
rescue
render text: "HEAP DUMP:\nnot supported", content_type: Mime::TEXT
end
end
end end

View file

@ -1,3 +1,8 @@
if ENV['DISCOURSE_DUMP_HEAP'] == "1"
require 'objspace'
ObjectSpace.trace_object_allocations_start
end
require 'rubygems' require 'rubygems'
# Set up gems listed in the Gemfile. # Set up gems listed in the Gemfile.

View file

@ -181,6 +181,7 @@ Discourse::Application.routes.draw do
end end
get "memory_stats"=> "diagnostics#memory_stats", constraints: AdminConstraint.new get "memory_stats"=> "diagnostics#memory_stats", constraints: AdminConstraint.new
get "dump_heap"=> "diagnostics#dump_heap", constraints: AdminConstraint.new
end # admin namespace end # admin namespace

View file

@ -10,6 +10,7 @@ require "fileutils"
@best_of = 1 @best_of = 1
@mem_stats = false @mem_stats = false
@unicorn = false @unicorn = false
@dump_heap = false
opts = OptionParser.new do |o| opts = OptionParser.new do |o|
o.banner = "Usage: ruby bench.rb [options]" o.banner = "Usage: ruby bench.rb [options]"
@ -26,6 +27,11 @@ opts = OptionParser.new do |o|
o.on("-b", "--best_of [NUM]", "Number of times to run the bench taking best as result") do |i| o.on("-b", "--best_of [NUM]", "Number of times to run the bench taking best as result") do |i|
@best_of = i.to_i @best_of = i.to_i
end end
o.on("-d", "--heap_dump") do
@dump_heap = true
# We need an env var for config/boot.rb to enable allocation tracing prior to framework init
ENV['DISCOURSE_DUMP_HEAP'] = "1"
end
o.on("-m", "--memory_stats") do o.on("-m", "--memory_stats") do
@mem_stats = true @mem_stats = true
end end
@ -103,18 +109,18 @@ end
ENV["RAILS_ENV"] = "profile" ENV["RAILS_ENV"] = "profile"
gc_env_vars = %w(RUBY_GC_HEAP_INIT_SLOTS RUBY_GC_HEAP_FREE_SLOTS RUBY_GC_HEAP_GROWTH_FACTOR RUBY_GC_HEAP_GROWTH_MAX_SLOTS RUBY_GC_MALLOC_LIMIT RUBY_GC_OLDMALLOC_LIMIT RUBY_GC_MALLOC_LIMIT_MAX RUBY_GC_OLDMALLOC_LIMIT_MAX RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR) discourse_env_vars = %w(DISCOURSE_DUMP_HEAP RUBY_GC_HEAP_INIT_SLOTS RUBY_GC_HEAP_FREE_SLOTS RUBY_GC_HEAP_GROWTH_FACTOR RUBY_GC_HEAP_GROWTH_MAX_SLOTS RUBY_GC_MALLOC_LIMIT RUBY_GC_OLDMALLOC_LIMIT RUBY_GC_MALLOC_LIMIT_MAX RUBY_GC_OLDMALLOC_LIMIT_MAX RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR)
if @include_env if @include_env
puts "Running with tuned environment" puts "Running with tuned environment"
ENV["RUBY_GC_MALLOC_LIMIT"] = "50_000_000" ENV["RUBY_GC_MALLOC_LIMIT"] = "50_000_000"
gc_env_vars - %w(RUBY_GC_MALLOC_LIMIT).each do |v| discourse_env_vars - %w(RUBY_GC_MALLOC_LIMIT).each do |v|
ENV.delete v ENV.delete v
end end
else else
# clean env # clean env
puts "Running with the following custom environment" puts "Running with the following custom environment"
gc_env_vars.each do |w| discourse_env_vars.each do |w|
puts "#{w}: #{ENV[w]}" puts "#{w}: #{ENV[w]}"
end end
end end
@ -256,6 +262,11 @@ begin
puts open("http://127.0.0.1:#{@port}/admin/memory_stats#{append}").read puts open("http://127.0.0.1:#{@port}/admin/memory_stats#{append}").read
end end
if @dump_heap
puts
puts open("http://127.0.0.1:#{@port}/admin/dump_heap#{append}").read
end
if @result_file if @result_file
File.open(@result_file,"wb") do |f| File.open(@result_file,"wb") do |f|
f.write(results) f.write(results)