diff --git a/.travis.yml b/.travis.yml index 3a01754..24e755b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,18 +6,21 @@ rvm: - 2.3 - 2.4 - 2.5 + - &latest_ruby 2.6 - ruby-head - jruby-head # - rbx-2 -sudo: false - addons: apt: packages: - libgmp3-dev matrix: + include: + - rvm: *latest_ruby + script: bundle exec rake memory_profile:run + name: Profiling Memory Usage allow_failures: - rvm: ruby-head - rvm: jruby-head diff --git a/Gemfile b/Gemfile index 37ffe1d..ddff94a 100644 --- a/Gemfile +++ b/Gemfile @@ -8,6 +8,7 @@ gemspec group :benchmark, :test do gem 'benchmark-ips' gem 'memory_profiler' + gem 'terminal-table' install_if -> { RUBY_PLATFORM !~ /mingw|mswin|java/ } do gem 'stackprof' diff --git a/performance/memory_profile.rb b/performance/memory_profile.rb index bfacde8..9a15375 100644 --- a/performance/memory_profile.rb +++ b/performance/memory_profile.rb @@ -2,25 +2,61 @@ require 'benchmark/ips' require 'memory_profiler' +require 'terminal-table' require_relative 'theme_runner' -def profile(phase, &block) - puts - puts "#{phase}:" - puts +class Profiler + LOG_LABEL = "Profiling: ".rjust(14).freeze + REPORTS_DIR = File.expand_path('.memprof', __dir__).freeze - report = MemoryProfiler.report(&block) + def self.run + puts + yield new + end - report.pretty_print( - color_output: true, - scale_bytes: true, - detailed_report: true - ) + def initialize + @allocated = [] + @retained = [] + @headings = [] + end + + def profile(phase, &block) + print LOG_LABEL + print "#{phase}.. ".ljust(10) + report = MemoryProfiler.report(&block) + puts 'Done.' + @headings << phase.capitalize + @allocated << "#{report.scale_bytes(report.total_allocated_memsize)} (#{report.total_allocated} objects)" + @retained << "#{report.scale_bytes(report.total_retained_memsize)} (#{report.total_retained} objects)" + + return if ENV['CI'] + require 'fileutils' + report_file = File.join(REPORTS_DIR, "#{sanitize(phase)}.txt") + FileUtils.mkdir_p(REPORTS_DIR) + report.pretty_print(to_file: report_file, scale_bytes: true) + end + + def tabulate + table = Terminal::Table.new(headings: @headings.unshift('Phase')) do |t| + t << @allocated.unshift('Total allocated') + t << @retained.unshift('Total retained') + end + + puts + puts table + puts "\nDetailed report(s) saved to #{REPORTS_DIR}/" unless ENV['CI'] + end + + def sanitize(string) + string.downcase.gsub(/[\W]/, '-').squeeze('-') + end end Liquid::Template.error_mode = ARGV.first.to_sym if ARGV.first -profiler = ThemeRunner.new - -profile("Parsing") { profiler.compile } -profile("Rendering") { profiler.render } +runner = ThemeRunner.new +Profiler.run do |x| + x.profile('parse') { runner.compile } + x.profile('render') { runner.render } + x.tabulate +end