檢視原始碼 效能分析

切勿臆測效能瓶頸

即使是經驗豐富的軟體開發人員,也常常猜錯程式中的效能瓶頸所在。因此,請分析您的程式以找出效能瓶頸,並專注於最佳化這些瓶頸。

Erlang/OTP 包含數個工具,可協助您找出瓶頸

  • tprof 是一個追蹤效能分析器,可以測量每次函數呼叫的呼叫次數、呼叫時間或堆積配置。
  • fprof 提供最詳細的程式時間花費資訊,但它會顯著降低所分析程式的速度。
  • dbg 是一般 Erlang 追蹤前端。透過使用 timestampcpu_timestamp 選項,可用於計時即時系統中函數呼叫所花費的時間。
  • lcnt 用於尋找 Erlang 執行時期系統內部鎖定機制中的爭用點。當尋找程序、埠、ETS 表格以及其他可以並行運行的實體之間互動的瓶頸時,它非常有用。

這些工具在工具中有更詳細的說明。

Erlang/OTP 之外也有數個開源工具,可用於協助效能分析。其中一些工具是

  • erlgrind 可用於在 kcachegrind 中視覺化 fprof 資料。

  • eflame 是 fprof 的替代方案,會將效能分析輸出顯示為火焰圖。

  • recon 是 Erlang 效能分析和除錯工具的集合。此工具隨附一本名為Erlang in Anger 的電子書。

  • perf 是一個適用於 Linux 的取樣效能分析器,提供類似於 fprof 的功能,但開銷低得多。當模擬器以 +JPperf true 模擬器標誌啟動時,才可以分析 Erlang 程式碼,而且僅在啟用 JIT 時才可用。

    如需有關如何執行 perf 的詳細資訊,請參閱 BeamAsm 內部文件中的perf 支援章節。

記憶體效能分析

eheap_alloc: Cannot allocate 1234567890 bytes of memory (of type "heap").

上述口號是 Erlang 終止的更常見原因之一。由於不明原因,Erlang 執行時期系統未能配置要使用的記憶體。發生這種情況時,會產生當機傾印,其中包含系統在記憶體不足時的狀態資訊。使用crashdump_viewer來檢視正在使用的記憶體。尋找具有大量堆積或大量訊息的程序、大型 ETS 表格等等。

在檢視執行中系統的記憶體使用情況時,取得資訊的最基本函式是 erlang:memory()。它會傳回系統目前的記憶體使用情況。instrument 可用於取得更詳細的記憶體使用位置分析。

然後可以使用各自的資訊函式來檢查程序、埠和 ETS 表格,也就是 process_info/2erlang:port_info/2ets:info/1

有時系統可能會進入一種狀態,其中從 erlang:memory(total) 回報的記憶體與作業系統回報的記憶體差異很大。其中一個原因是 Erlang 執行時期系統內的內部碎片。可以使用 erlang:system_info(allocator) 來擷取有關記憶體配置方式的資料。從該函式取得的資料是原始且難以閱讀。recon_alloc 可用於從 system_info 統計計數器中擷取有用的資訊。

大型系統

對於大型系統,一開始在模擬且有限的情境中執行效能分析可能會很有趣。但是,瓶頸往往只會在許多事情同時發生且涉及多個節點時才會出現或造成問題。因此,也希望在真實目標系統上的系統測試工廠中執行效能分析。

對於大型系統,您不希望在整個系統上執行效能分析工具。相反地,您希望專注於佔據大部分執行時間的中央程序和模組。

還有一些工具可用於檢視整個系統,開銷或多或少。

  • observer 是一個 GUI 工具,可以連線到遠端節點,並顯示有關執行中系統的各種資訊。
  • etop 是一個命令列工具,可以連線到遠端節點,並顯示類似於 UNIX 工具 top 顯示的資訊。
  • msacc 允許使用者檢視 Erlang 執行時期系統正在花費時間做什麼。開銷非常低,這使得它在重載系統中執行以了解從哪裡開始進行更精細的效能分析非常有用。

要尋找的內容

在分析效能分析活動的結果檔案時,尋找呼叫多次且具有較長「自身」執行時間(不包括呼叫其他函式的時間)的函式。呼叫多次的函式也可能很有趣,因為即使是很小的東西,如果重複多次也可能會加起來相當多。此外,也要問自己可以做些什麼來減少這個時間。以下是要問自己的適當類型問題

  • 是否有可能減少呼叫函式的次數?
  • 如果變更測試順序,是否可以減少測試的執行頻率?
  • 是否可以移除任何多餘的測試?
  • 是否有任何計算的運算式每次都給出相同的結果?
  • 是否有其他等效且更有效率的方法來執行此操作?
  • 是否可以使用其他內部資料表示來提高效率?

這些問題並不總是很容易回答。可能需要一些基準測試來支持您的理論,並避免在您的理論錯誤時讓事情變慢。如需詳細資訊,請參閱基準測試

工具

fprof

fprof 會測量每個函式的執行時間,包括自身時間,也就是函式用於自身執行的時間,以及累計時間,也就是包含呼叫的函式。這些值會依程序顯示。您也會知道每個函式被呼叫的次數。

fprof 基於追蹤至檔案,以盡量減少執行時效能影響。使用 fprof 只是呼叫一些程式庫函式,請參閱工具中的 fprof 手冊頁面。

eprof

eprof 基於 Erlang trace_info BIF。 eprof 顯示每個程序使用了多少時間,以及這些時間花費在哪些函式呼叫中。時間以總時間和絕對時間的百分比顯示。如需詳細資訊,請參閱工具中的 eprof 手冊頁面。

cprof

cprof 在功能方面介於 fprofcover 之間。它會計算程式執行時每個函式被呼叫的次數,以每個模組為基礎。cprof 的效能降低效果很低(與 fprof 相比),並且不需要重新編譯任何要分析的模組(與 cover 相比)。如需詳細資訊,請參閱工具中的 cprof 手冊頁面。

工具摘要

工具結果結果大小對程式執行時間的影響記錄呼叫次數記錄執行時間記錄呼叫者記錄垃圾收集
fprof每個程序到螢幕/檔案大型顯著減速總計和自身
eprof每個程序/函式到螢幕/檔案小幅減速僅總計
cprof每個模組到呼叫者小型小幅減速

表格:工具摘要

dbg

dbg 是一般 Erlang 追蹤工具。透過使用 timestampcpu_timestamp 選項,它可以作為精密的工具來分析特定程序的函數呼叫所花費的時間。當試圖了解時間花費在重載系統中的哪個位置時,這非常有用,因為可以將分析的範圍限制得非常小。如需詳細資訊,請參閱執行時期工具中的 dbg 手冊頁面。

lcnt

lcnt 用於分析並行運行的實體之間的互動。例如,如果您有一個系統中所有其他程序都需要互動的程序(也許它有一些全域組態),那麼可以使用 lcnt 來判斷與該程序的互動是否存在問題。

在 Erlang 執行期系統中,實體只有在有多個排程器時才會平行執行。因此,lcnt 在使用多核心多排程器的系統上會顯示更多的競爭點(因此更有用)。

欲了解更多資訊,請參閱 Tools 中的 lcnt 手冊頁面。