V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
OneAPM
V2EX  ›  Ruby on Rails

Ruby Profiler 详解之 stackprof

  •  9
     
  •   OneAPM · 2015-07-09 16:07:40 +08:00 · 2971 次点击
    这是一个创建于 3205 天前的主题,其中的信息可能已经有所发展或是发生改变。

    简介

    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>
    

    这里可以很明显的看出是 m2 方法比较慢,占据了大部分的执行时间,相比其他的调优工具,它只是列出了用户自己的方法所占时间比,在 ruby-prof 中的测试中,它是会显示String#*这个方法的占比的,但是对于我们来说,它的意义不大,而 stackprof 是不会理会标准库里的方法的。同时 stackprof 也是可以过滤方法的,比如我们发现了 m2 这个方法有问题,那么就可以把它过滤出来,看看细节:

    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
    

    我们可以看到 m2 这个方法定义在哪一个文件的哪一行,同时是谁调用了它,以及还显示了它在源码中的上下文。假如有多个方法调用了 m2 ,还会显示出这几个方法,以及他们调用 m2 所占的比例,也就是上面的 callers 部分,因为只有一个 start 方法调用了 m2,所以它是 100% 。

    在rack中的使用方法

    stackprof 本身实现了一个 rack middleware ,所以可以很方便的挂载到一个 rack 应用中:

    use StackProf::Middleware, enabled: true, mode: :cpu, save_every: 5
    

    在 rails 中使用,先在 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
    

    可以利用这样的方式调试线上的环境。

    参考链接:


    本文系OneAPM工程师原创文章。OneAPM是中国基础软件领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和SQL语句的实时抓取。想阅读更多技术文章,请访问OneAPM官方技术博客

    1 条回复    2016-10-04 18:25:15 +08:00
    venson
        1
    venson  
       2016-10-04 18:25:15 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3692 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 00:16 · PVG 08:16 · LAX 17:16 · JFK 20:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.