檢視原始碼 效能評測

效能評測的主要目的是找出給定演算法或函數哪種實作方式最快。效能評測並非精確的科學。現今的作業系統通常會執行難以關閉的背景任務。快取和多核心 CPU 並不利於效能評測。在進行效能評測時,最好在單一使用者模式下執行 UNIX 電腦,但對於隨意的測試來說,這至少是不方便的。

使用 erlperf

一個有用的效能評測工具是 erlperf (文件)。它可以簡單地找出哪個程式碼比較快。例如,以下是如何比較兩種產生隨機位元組的方法

% erlperf 'rand:bytes(2).' 'crypto:strong_rand_bytes(2).'
Code                                 ||        QPS       Time   Rel
rand:bytes(2).                        1    7784 Ki     128 ns  100%
crypto:strong_rand_bytes(2).          1    2286 Ki     437 ns   29%

時間 欄位我們可以讀出,平均來說,呼叫 rand:bytes(2) 需要 128 奈秒,而呼叫 crypto:strong_rand_bytes(2) 需要 437 奈秒。

QPS 欄位我們可以讀出每秒可以進行多少次呼叫。對於 rand:bytes(2),每秒可以進行 7,784,000 次呼叫。

Rel 欄位顯示相對差異,其中 100% 表示最快的程式碼。

當一次產生兩個隨機位元組時,rand:bytes/1crypto:strong_rand_bytes/1 快三倍以上。假設我們真的需要強隨機數,而且我們需要盡可能快地取得它們,我們該怎麼辦?一種方法可以是一次產生超過兩個位元組。

% erlperf 'rand:bytes(100).' 'crypto:strong_rand_bytes(100).'
Code                                   ||        QPS       Time   Rel
rand:bytes(100).                        1    2124 Ki     470 ns  100%
crypto:strong_rand_bytes(100).          1    1915 Ki     522 ns   90%

當我們一次產生 100 個位元組時,rand:bytes/1 仍然比較快,但相對差異較小。

% erlperf 'rand:bytes(1000).' 'crypto:strong_rand_bytes(1000).'
Code                                    ||        QPS       Time   Rel
crypto:strong_rand_bytes(1000).          1    1518 Ki     658 ns  100%
rand:bytes(1000).                        1     284 Ki    3521 ns   19%

當我們一次產生 1000 個位元組時,crypto:strong_rand_bytes/1 現在是最快的。

使用 Erlang/OTP 功能進行效能評測

效能評測可以測量實際時間或 CPU 時間。

  • timer:tc/3 測量實際時間。實際時間的優點是,I/O、交換以及作業系統核心中的其他活動都包含在測量中。缺點是測量結果通常變化很大。通常最好多次運行效能評測,並記錄最短的時間,這是在最佳情況下可能實現的最小時間。

  • statistics(runtime) 測量在 Erlang 虛擬機器中花費的 CPU 時間。CPU 時間的優點是,結果在不同運行之間更加一致。缺點是不包含在作業系統核心中花費的時間(例如交換和 I/O)。因此,如果涉及任何 I/O(檔案或 socket),測量 CPU 時間會產生誤導。

同時進行實際時間測量和 CPU 時間測量可能是一個好主意。

一些最後的建議

  • 兩種測量類型的粒度都可能很高。因此,請確保每次測量至少持續幾秒鐘。
  • 為了使測試公平,每次新的測試運行都要在自己新建立的 Erlang 進程中執行。否則,如果所有測試都在同一個進程中執行,後面的測試會以較大的堆積大小開始,因此可能執行的垃圾回收較少。也請考慮在每次測試之間重新啟動 Erlang 模擬器。
  • 不要假設在電腦架構 X 上給定演算法最快的實作方式,在電腦架構 Y 上也是最快的。