Ruby Profiler詳細stackprof

6021 ワード

概要
stackprofはサンプリングに基づくチューニングツールですが、サンプリングにはどのようなメリットがありますか?メリットは、オンラインで使用して、内蔵のアルゴリズムに従ってデータの一部をキャプチャし、パフォーマンスのほんの一部に影響を与えることです.一連のdumpファイルが生成され、オンラインでこれらのファイルを分析して問題を特定します.googleにはサンプリングに基づく論文があり、サンプリングが可能であることも基本的に証明されています.stackprofもgoogleのperftoolsの影響を受け、サンプリング方式でチューニングしています.
基本的な使い方
StackProf.run(mode: :cpu, out: './stackprof.dump') do
  #     
end

ここでは、テストの目的としてサンプルコードを示します.
require "stackprof"

class Compute

  def m1
    "string" * 100
  end

  def m2
    "string" * 10000
  end

  def start
    100_000.times do
      m1
      m2
    end
  end
end

StackProf.run(mode: :cpu, out: './stackprof.dump') do
  Compute.new.start
end
test.rbとして保存するruby testを実行する.rbは現在のディレクトリの下でstackprofを生成する.dumpファイルstackprofでこのファイルを開きます.
stackprof stackprof.dump --text
==================================
  Mode: cpu(1000)
  Samples: 1793 (0.61% miss rate)
  GC: 587 (32.74%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
      1106  (61.7%)        1106  (61.7%)     Compute#m2
        98   (5.5%)          98   (5.5%)     Compute#m1
      1206  (67.3%)           2   (0.1%)     block in Compute#start
      1206  (67.3%)           0   (0.0%)     <main>
      1206  (67.3%)           0   (0.0%)     Compute#start
      1206  (67.3%)           0   (0.0%)     <main>
      1206  (67.3%)           0   (0.0%)     block in <main>

ここでは、m 2メソッドが遅いことが明らかになり、実行時間の大部分を占めており、他のチューニングツールに比べて、ユーザー自身のメソッドが占める時間比をリストしているだけで、ruby-profのテストではString#*というメソッドの割合を示していますが、私たちにとって、その意味は大きくありません.stackprofは標準ライブラリの方法を気にしない.同時にstackprofも濾過方法であり、例えばm 2という方法に問題があることを発見したら、それを濾過して詳細を見ることができます.
stackprof stackprof.dump --text --method 'Compute#m2'

Compute#m2 (/Users/lizhe/Workspace/ruby-performance-tuning/test.rb:9)
  samples:  1106 self (61.7%)  /   1106 total (61.7%)
  callers:
    1106  (  100.0%)  block in Compute#start
  code:
                                  |     9  |   end
 1106   (61.7%) /  1106  (61.7%)  |    10  |
                                  |    11  |   def start

m 2という方法では、どのファイルのどの行を定義するか、同時に誰が呼び出したか、ソースコードのコンテキストも表示されます.複数のメソッドがm 2を呼び出すと、これらのメソッドと、m 2を呼び出す割合、すなわち上のcallers部分が表示されます.startメソッドがm 2を呼び出すのは1つだけなので、100%です.
rackでの使い方
stackprof自体はrack middlewareを実現しているので、rackアプリケーションに簡単にマウントできます.
use StackProf::Middleware, enabled: true, mode: :cpu, save_every: 5

レールで使用するには、Gemfileにstackprofを追加してからmiddlewareを追加します.
config.middleware.use StackProf::Middleware, enabled: true, mode: :cpu, save_every: 5

その後、アプリケーションをリクエストし、何回かリクエストします.5秒ごとに出力結果をtmpディレクトリに保存し、結果を表示します.
==================================
  Mode: cpu(1000)
  Samples: 155 (0.00% miss rate)
  GC: 11 (7.10%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
        18  (11.6%)          18  (11.6%)     Hike::Index#entries
        12   (7.7%)          12   (7.7%)     Hike::Index#stat
         9   (5.8%)           9   (5.8%)     #<Module:0x007fb72a0c7b08>.load_with_autoloading
        18  (11.6%)           9   (5.8%)     Sprockets::Cache::FileStore#[]
         6   (3.9%)           6   (3.9%)     block (2 levels) in BindingOfCaller::BindingExtensions#callers
         5   (3.2%)           5   (3.2%)     Time.parse
         5   (3.2%)           5   (3.2%)     Sprockets::Mime#mime_types
         5   (3.2%)           5   (3.2%)     Pathname#chop_basename
         4   (2.6%)           4   (2.6%)     block in ActionView::PathResolver#find_template_paths
         4   (2.6%)           4   (2.6%)     block in BetterErrors::ExceptionExtension#set_backtrace
        15   (9.7%)           3   (1.9%)     block in ActiveSupport::Dependencies#load_file
         2   (1.3%)           2   (1.3%)     Temple::Mixins::CompiledDispatcher::DispatchNode#initialize
         5   (3.2%)           2   (1.3%)     ActionDispatch::Cookies::EncryptedCookieJar#initialize
         2   (1.3%)           2   (1.3%)     ActiveSupport::KeyGenerator#generate_key
         2   (1.3%)           2   (1.3%)     block in ActionView::PathResolver#query
         4   (2.6%)           2   (1.3%)     Slim::Parser#initialize
       113  (72.9%)           2   (1.3%)     ActionView::Renderer#render_template
         2   (1.3%)           2   (1.3%)     Hike::Trail#stat
         2   (1.3%)           2   (1.3%)     block in ActiveSupport::Dependencies#search_for_file
        22  (14.2%)           2   (1.3%)     block in Temple::Filters::MultiFlattener#on_multi
        20  (12.9%)           2   (1.3%)     Temple::Filters::ControlFlow#dispatcher
        15   (9.7%)           2   (1.3%)     ActionView::Renderer#render_partial
         1   (0.6%)           1   (0.6%)     block in Slim::Parser#initialize
         1   (0.6%)           1   (0.6%)     Pathname#prepend_prefix
         1   (0.6%)           1   (0.6%)     String#blank?
         1   (0.6%)           1   (0.6%)     ActiveSupport::SafeBuffer#initialize
        10   (6.5%)           1   (0.6%)     Sprockets::Asset#dependency_fresh?
         1   (0.6%)           1   (0.6%)     Sprockets::Asset#init_with
         1   (0.6%)           1   (0.6%)     Hike::Index#sort_matches
         1   (0.6%)           1   (0.6%)     block in ActiveSupport::Dependencies::Loadable#require

このような方法でライン上の環境をデバッグすることができます.
リファレンスリンク
  • https://github.com/tmm1/stackprof

  • 本文はOneAPMエンジニアの李哲のオリジナル文章である.詳細については、OneAPM 公式技術ブログを参照してください.