Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rubyでのプロファイリング

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for ta1kt0me ta1kt0me
January 22, 2016

 Rubyでのプロファイリング

Avatar for ta1kt0me

ta1kt0me

January 22, 2016
Tweet

More Decks by ta1kt0me

Other Decks in Technology

Transcript

  1. ४උ # lib/app_profiler.rb module AppProfiler def run StackProf.run(mode: :cpu, out:

    'tmp/profile.dump', raw: true) do super end end end FooBatch.prepend Profiler
  2. ଌ⏰Δ $ time bundle exec rails runner ‘require ”app_profiler”;FooBatch.execute’ bundle

    exec rails runner 3.24s user 0.61s system 0% cpu 2:05:06.16 total
  3. ௐ΂Δ $ bundle exec stackprof tmp/profile.dump ================================== Mode: cpu(1000) Samples:

    5687375 (0.01% miss rate) GC: 86731 (1.52%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 5045720 (88.7%) 5045720 (88.7%) Mysql2::Result#each 96460 (1.7%) 64387 (1.1%) ActiveRecord::LazyAttributeHash#[] 52823 (0.9%) 52738 (0.9%) Mysql2::Client#query 27139 (0.5%) 27139 (0.5%) ActiveRecord::Attribute#initialize 20650 (0.4%) 20650 (0.4%) block in ActiveRecord::Result#hash_rows ………
  4. ଌ⏰Δ $ time bundle exec rails runner ‘require “app_profiler";FooBatch.execute' bundle

    exec rails runner 3.37s user 0.45s system 0% cpu 11:39.89 total
  5. ௐ΂Δ • αϯϓϧ਺ • 5687375 -> 436714 • GCൃੜճ਺ •

    86731 -> 12812 • Mysql2::Result#eachͷݺͼग़͠αϯϓϧ਺ • 5045720 -> 285386
  6. benchmark require 'benchmark' module AppProfiler def run puts Benchmark::CAPTION puts

    Benchmark.measure { super } end end FooBatch.prepend Profiler $ bundle exec rails runner 'require "app_profiler";FooBatch.execute' user system total real 0.260000 0.120000 0.380000 ( 0.437103) )
  7. benchmark-ips require 'benchmark/ips' nums = 1_000_000.times.map { rand } Benchmark.ips

    do |x| x.report('last') { nums.last } x.report('minus one index') { nums[-1] } x.report('last one index') { nums[nums.length - 1] } x.compare! end alculating ------------------------------------- last 123.090k i/100ms minus one index 125.563k i/100ms last one index 124.122k i/100ms ------------------------------------------------- last 8.163M (±11.6%) i/s - 40.004M minus one index 9.364M (± 9.2%) i/s - 46.333M last one index 8.506M (± 6.8%) i/s - 42.326M Comparison: minus one index: 9364326.4 i/s last one index: 8506110.5 i/s - 1.10x slower last: 8162777.3 i/s - 1.15x slower
  8. profile $ bundle exec rails runner 'require "profile"; FooBatch.execute' 2>

    tmp/profile.txt % cumulative self self total time seconds seconds calls ms/call ms/call name 7.22 0.13 0.13 49 2.65 9.80 Kernel#require 3.89 0.20 0.07 1645 0.04 0.98 Array#each 3.33 0.26 0.06 2749 0.02 0.11 BindingOfCaller::BindingExtensions#callers 2.78 0.31 0.05 1106 0.05 0.06 Mail::Field#responsible_for? 2.78 0.36 0.05 26 1.92 1.92 Dir.[] 2.22 0.40 0.04 2860 0.01 0.08 BetterErrors::ExceptionExtension#set_backtrace 2.22 0.44 0.04 8 5.00 10.00 Mail::Parsers::Ragel::AddressListsMachine.parse 1.67 0.47 0.03 37 0.81 2.97 Kernel#loop 1.67 0.50 0.03 185 0.16 0.16 Module#module_eval ……
  9. ruby-prof module AppProfiler def run result = RubyProf.profile do super

    end printer = RubyProf::FlatPrinter.new(result) File.open('tmp/ruby_prof.txt', 'w') { |file| printer.print(file) } end end FooBatch.prepend AppProfiler $ bundle exec rails runner 'require "app_profiler"; FooBatch.execute' $ head -13 tmp/ruby_prof.txt Measure Mode: wall_time Thread ID: 70360380996060 Fiber ID: 70360318592320 Total: 0.602138 Sort by: self_time %self total self wait child calls name 6.55 0.040 0.039 0.000 0.000 16 Mysql2::Client#_query 4.44 0.249 0.027 0.000 0.222 41 *Kernel#require 3.63 0.022 0.022 0.000 0.000 13 <Class::Dir>#[] 1.99 0.012 0.012 0.000 0.000 7 Module#inspect 1.70 0.010 0.010 0.000 0.000 5939 Symbol#to_s 1.33 0.026 0.008 0.000 0.018 542 *Module#class_eval
  10. rblineprof • https://github.com/tmm1/rblineprof • Rubyͷ2.1Ҏ্ͩͱmasterΛ࢖͏ඞཁ͕͋Δ • https://github.com/tmm1/rblineprof/pull/27 • ࣮ߦߦ͝ͱͷॲཧ࣌ؒΛϓϩϑΝΠϧ͢Δ •

    σϑΥϧτͩͱϨϙʔτػೳ͕ͳ͍ͷͰɺrblineprof-reportΛ Ұॹʹ࢖͏ͱྑ͍ײ͡ • https://github.com/sonots/rblineprof-report
  11. ruby-prof module AppProfiler def run result = RubyProf.profile do super

    end printer = RubyProf::CallStackPrinter.new(result) File.open('tmp/profile.html', 'w') { |file| printer.print(file) } end end FooBatch.prepend AppProfiler $ bundle exec rails runner 'require "app_profiler"; FooBatch.execute' $ head -13 tmp/ruby_prof.txt Measure Mode: wall_time Thread ID: 70360380996060 Fiber ID: 70360318592320 Total: 0.602138 Sort by: self_time %self total self wait child calls name 6.55 0.040 0.039 0.000 0.000 16 Mysql2::Client#_query 4.44 0.249 0.027 0.000 0.222 41 *Kernel#require 3.63 0.022 0.022 0.000 0.000 13 <Class::Dir>#[] 1.99 0.012 0.012 0.000 0.000 7 Module#inspect 1.70 0.010 0.010 0.000 0.000 5939 Symbol#to_s 1.33 0.026 0.008 0.000 0.018 542 *Module#class_eval
  12. rbtrace $ bundle exec rbtrace -p $RUBY_PID -m show #

    p: pid, m: method name *** attached to process 21066 FoosController#show <1.182228> *** detached from process 21066