DIY Ruby CPU 分析——Part I

【編者按】原文做者 Emil Soman,Rubyist,除此以外居然同時也是藝術家,吉他手**,Garden City RubyConf 組織者。本文是DIY Ruby CPU Profiling 的第一部分,由 OneAPM 工程師編譯整理。**html

alt

在 Codemancers,咱們正在建設 Rbkit——一個針對 Ruby 語言的——擁有新炫酷功能的代碼分析器。我目前正在實現一個嵌在 rbkit gem 裏的 CPU 分析器,這將有助 rbkit UI 重建分析 Ruby 進程調用圖,並在屏幕上得出有用的可視化展現。在這個過程當中,我學到了許多新東西,很樂意在本系列的博客文章中與您分享。ruby

咱們打算一步一步從基礎開始,專門爲 Ruby 編寫一個初級的 CPU 分析器!在完成時咱們將學到:服務器

  • 什麼是 CPU 分析工具

  • 分析模式——工具和採樣性能

  • CPU Time 和 Wall Time ——它們分別是什麼意思,如何測量?code

  • 寫一個簡單的 C 擴展並用於 Ruby 中htm

  • Ruby Tracepoints——調用和返回進程

  • C 語言中的信號處理get

  • 用一個信號暫停 Ruby 進程並用調用堆查看博客

  • 用分析數據進行一些有用但笨拙的試驗 ###Part I. 介紹 CPU 分析 經過對你的程序進行 CPU 分析,能夠發現相較於 CPU 使用率,你的程序是多麼寶貴。爲了分析程序,你須要使用一個分析工具並按照下列步驟操做:

  • 開始 CPU 剖析

  • 執行你想要分析的代碼

  • 中止 CPU 剖析並獲得剖析結果

  • 分析結果

  • 經過分析剖析結果,你會發現使整個程序緩慢的瓶頸。

####分析模式

CPU 剖析能夠分爲如下兩種方法:

####1. 工具 在這種模式下,分析工具利用一些 hooks,由解釋器提供或者插入程序中,來了解調用圖並測量在調用圖中每一個方法的執行時間。舉個例子,看一下下面這段 Ruby 代碼:

def main
3.times do
find_many_square_roots
find_many_squares
end
end


def find_many_square_roots
5000.times{|i| Math.sqrt(i)}
end

def find_many_squares
5000.times{|i| i**2 }
end

main

我已經插入了一些內容,來幫助瞭解若是 Ruby 解釋器給了咱們方法的調用和返回的 hooks,它們如何執行:

def main
# method call hook gets executed
3.times do
find_many_square_roots
find_many_squares
end
# method end hook gets executed
end

def find_many_square_roots
# method call hook gets executed
5000.times{|i| Math.sqrt(i)}
# method end hook gets executed
end

def find_many_squares
# method call hook gets executed
5000.times{|i| i**2 }
# method end hook gets executed
end

main

如今,若是咱們可以打印出當前時間和這些 hooks 內部當前方法的名稱,會獲得看起來像這種形式的輸出結果:

sec:00 usec:201007	called  	main
sec:00 usec:201108	called  	find_many_square_roots
sec:00 usec:692123	returned	find_many_square_roots
sec:00 usec:692178	called  	find_many_squares
sec:00 usec:846540	returned	find_many_squares
sec:00 usec:846594	called  	find_many_square_roots
sec:01 usec:336166	returned	find_many_square_roots
sec:01 usec:336215	called  	find_many_squares
sec:01 usec:484880	returned	find_many_squares
sec:01 usec:484945	called  	find_many_square_roots
sec:01 usec:959254	returned	find_many_square_roots
sec:01 usec:959315	called  	find_many_squares
sec:02 usec:106474	returned	find_many_squares
sec:02 usec:106526	returned	main`

正如你所看到的,此輸出能夠告訴咱們在每一種方法裏面花了多長時間。同時也告訴咱們,每個方法調用的次數。這大概就解釋了性能分析工具是如何工做的。

######優勢:

高精度 咱們獲得了方法調用數 易於實施

######缺點:

每一個被分析的方法執行 hooks 時的額外開銷

####2. 採樣

在採樣模式下,分析器每隔 x 時間單元打斷一次程序,並查看調用堆並記錄它的信息(被稱爲「樣品」)。一旦該程序完成運行,分析器收集全部樣品並找出每一個方法出如今全部樣品中的次數。 很難想象?讓咱們來看看一樣的例子代碼,看看若是咱們使用採樣分析器,輸出結果會有怎樣的不一樣。 採樣分析器的輸出結果以下:

Call stack at 0.5sec: main/find_many_square_roots
Call stack at 1.0sec: main/find_many_square_roots
Call stack at 1.5sec: main/find_many_square_roots
Call stack at 2.0sec: main/find_many_squares`

在這個例子中,程序每 0.5 秒被中斷一次而且調用堆棧被記錄。所以,經過這個程序執行的過程咱們獲得了 4 個樣品,find_many_square_roots 記錄於 3 個樣品中, find_many_squares 只存在於一個樣品中。從本次採樣中,咱們獲得 find_many_square_roots 佔用了 75% CPU,與此同時 find_many_squares 只佔用了 25% 的 CPU 。這就大概解釋了分析器是怎麼樣工做的。

######優勢:

與工具分析相比開銷可忽略不計 很容易找到緩慢/長時間運行的方法

######缺點:

不擅長測量短期運行的方法 咱們沒有獲得方法調用數 很難本身寫出採樣分析器

####歸納

咱們只是調查了 CPU 分析的含義和兩種經常使用的 CPU 分析方法。在第 2 部分,咱們將探討對描述 CPU 使用狀況的 2 個單位進行測量—— CPU Time 和 Wall Time。咱們也會親手寫一些代碼來獲取進行測量。感謝您的閱讀!

OneAPM for Ruby 可以深刻到全部 Ruby 應用內部完成應用性能管理和監控,包括代碼級別性能問題的可見性、性能瓶頸的快速識別與追溯、真實用戶體驗監控、服務器監控和端到端的應用性能管理。 想閱讀更多技術文章,請訪問 OneAPM 官方博客

相關文章
相關標籤/搜索