2017-06-20 07:10:37 -04:00
|
|
|
# frozen_string_literal: true
|
2010-10-29 19:50:57 -04:00
|
|
|
#
|
|
|
|
# purpose:
|
|
|
|
# Profile memory usage of each tests.
|
|
|
|
#
|
|
|
|
# usage:
|
2013-08-16 04:46:21 -04:00
|
|
|
# RUBY_TEST_ALL_PROFILE=[file] make test-all
|
2010-10-29 19:50:57 -04:00
|
|
|
#
|
|
|
|
# output:
|
2013-08-16 04:46:21 -04:00
|
|
|
# [file] specified by RUBY_TEST_ALL_PROFILE
|
|
|
|
# If [file] is 'true', then it is ./test_all_profile
|
2010-10-29 19:50:57 -04:00
|
|
|
#
|
|
|
|
# collected information:
|
|
|
|
# - ObjectSpace.memsize_of_all
|
|
|
|
# - GC.stat
|
2013-08-16 04:46:21 -04:00
|
|
|
# - /proc/meminfo (some fields, if exists)
|
|
|
|
# - /proc/self/status (some fields, if exists)
|
|
|
|
# - /proc/self/statm (if exists)
|
2010-10-29 19:50:57 -04:00
|
|
|
#
|
|
|
|
|
2013-08-16 04:46:21 -04:00
|
|
|
require 'objspace'
|
|
|
|
|
2010-10-29 19:50:57 -04:00
|
|
|
class MiniTest::Unit::TestCase
|
|
|
|
alias orig_run run
|
|
|
|
|
2013-08-16 04:46:21 -04:00
|
|
|
file = ENV['RUBY_TEST_ALL_PROFILE']
|
|
|
|
file = 'test-all-profile-result' if file == 'true'
|
|
|
|
TEST_ALL_PROFILE_OUT = open(file, 'w')
|
|
|
|
TEST_ALL_PROFILE_GC_STAT_HASH = {}
|
|
|
|
TEST_ALL_PROFILE_BANNER = ['name']
|
|
|
|
TEST_ALL_PROFILE_PROCS = []
|
2010-10-29 19:50:57 -04:00
|
|
|
|
2013-08-16 04:46:21 -04:00
|
|
|
def self.add *name, &b
|
|
|
|
TEST_ALL_PROFILE_BANNER.concat name
|
|
|
|
TEST_ALL_PROFILE_PROCS << b
|
|
|
|
end
|
|
|
|
|
2013-08-19 04:43:13 -04:00
|
|
|
add 'failed?' do |result, tc|
|
|
|
|
result << (tc.passed? ? 0 : 1)
|
|
|
|
end
|
|
|
|
|
|
|
|
add 'memsize_of_all' do |result, *|
|
2013-08-16 04:46:21 -04:00
|
|
|
result << ObjectSpace.memsize_of_all
|
2013-08-19 04:43:13 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
add *GC.stat.keys do |result, *|
|
2013-08-16 04:46:21 -04:00
|
|
|
GC.stat(TEST_ALL_PROFILE_GC_STAT_HASH)
|
|
|
|
result.concat TEST_ALL_PROFILE_GC_STAT_HASH.values
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.add_proc_meminfo file, fields
|
|
|
|
return unless FileTest.exist?(file)
|
|
|
|
regexp = /(#{fields.join("|")}):\s*(\d+) kB/
|
|
|
|
# check = {}; fields.each{|e| check[e] = true}
|
2013-08-19 04:43:13 -04:00
|
|
|
add *fields do |result, *|
|
2013-08-16 04:46:21 -04:00
|
|
|
text = File.read(file)
|
2013-08-19 04:43:13 -04:00
|
|
|
text.scan(regexp){
|
2013-08-16 04:46:21 -04:00
|
|
|
# check.delete $1
|
|
|
|
result << $2
|
|
|
|
''
|
|
|
|
}
|
|
|
|
# raise check.inspect unless check.empty?
|
2010-10-29 19:50:57 -04:00
|
|
|
end
|
2013-08-16 04:46:21 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
add_proc_meminfo '/proc/meminfo', %w(MemTotal MemFree)
|
|
|
|
add_proc_meminfo '/proc/self/status', %w(VmPeak VmSize VmHWM VmRSS)
|
|
|
|
|
|
|
|
if FileTest.exist?('/proc/self/statm')
|
2013-08-19 04:43:13 -04:00
|
|
|
add *%w(size resident share text lib data dt) do |result, *|
|
2013-08-16 04:46:21 -04:00
|
|
|
result.concat File.read('/proc/self/statm').split(/\s+/)
|
2010-10-29 19:50:57 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-08-16 04:46:21 -04:00
|
|
|
def memprofile_test_all_result_result
|
2013-08-16 05:10:06 -04:00
|
|
|
result = ["#{self.class}\##{self.__name__.to_s.gsub(/\s+/, '')}"]
|
2013-08-16 04:46:21 -04:00
|
|
|
TEST_ALL_PROFILE_PROCS.each{|proc|
|
2013-08-19 04:43:13 -04:00
|
|
|
proc.call(result, self)
|
2013-08-16 04:46:21 -04:00
|
|
|
}
|
|
|
|
result.join("\t")
|
|
|
|
end
|
|
|
|
|
2010-10-29 19:50:57 -04:00
|
|
|
def run runner
|
|
|
|
result = orig_run(runner)
|
2013-08-16 04:46:21 -04:00
|
|
|
TEST_ALL_PROFILE_OUT.puts memprofile_test_all_result_result
|
|
|
|
TEST_ALL_PROFILE_OUT.flush
|
2010-10-29 19:50:57 -04:00
|
|
|
result
|
|
|
|
end
|
2013-08-16 04:46:21 -04:00
|
|
|
|
|
|
|
TEST_ALL_PROFILE_OUT.puts TEST_ALL_PROFILE_BANNER.join("\t")
|
2010-10-29 19:50:57 -04:00
|
|
|
end
|