Benchmark - Perl 程式碼執行時間基準測試
use Benchmark qw(:all) ;
timethis ($count, "code");
# Use Perl code in strings...
timethese($count, {
'Name1' => '...code1...',
'Name2' => '...code2...',
});
# ... or use subroutine references.
timethese($count, {
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
});
# cmpthese can be used both ways as well
cmpthese($count, {
'Name1' => '...code1...',
'Name2' => '...code2...',
});
cmpthese($count, {
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
});
# ...or in two stages
$results = timethese($count,
{
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
},
'none'
);
cmpthese( $results ) ;
$t = timeit($count, '...other code...')
print "$count loops of other code took:",timestr($t),"\n";
$t = countit($time, '...other code...')
$count = $t->iters ;
print "$count loops of other code took:",timestr($t),"\n";
# enable hires wallclock timing if possible
use Benchmark ':hireswallclock';
Benchmark 模組封裝了許多例程,協助您找出執行某些程式碼所需的時間。
timethis - 多次執行一段程式碼
timethese - 多次執行多段程式碼
cmpthese - 將 timethese 的結果列印為比較圖表
timeit - 執行一段程式碼並查看執行時間
countit - 查看一段程式碼在特定時間內執行次數
傳回目前時間。範例
use Benchmark;
$t0 = Benchmark->new;
# ... your code here ...
$t1 = Benchmark->new;
$td = timediff($t1, $t0);
print "the code took:",timestr($td),"\n";
透過設定 $Benchmark::Debug
旗標來啟用或停用除錯
Benchmark->debug(1);
$t = timeit(10, ' 5 ** $Global ');
Benchmark->debug(0);
傳回反覆運算次數。
如果您使用 Benchmark 模組,下列常式將會匯出至您的名稱空間
引數:COUNT 是執行迴圈的次數,而 CODE 是要執行的程式碼。CODE 可以是程式碼參照或要評估的字串;不論哪一種,都會在呼叫者的套件中執行。
傳回:Benchmark 物件。
計時 CODE 的 COUNT 次反覆運算。CODE 可以是字串以評估或程式碼參照;不論哪一種,CODE 都會在呼叫者的套件中執行。結果將會印出至 STDOUT,格式為 TITLE 後接時間。如果未提供 TITLE,預設為「timethis COUNT」。STYLE 決定輸出的格式,如下方 timestr() 所述。
COUNT 可以為零或負數:這表示執行所需的最少 CPU 秒數。零表示預設值 3 秒。例如,至少執行 10 秒
timethis(-10, $code)
或至少執行 3 秒的兩個程式碼測試
timethese(0, { test1 => '...', test2 => '...'})
在 UNIX 術語中,CPU 秒數是使用者時間加上處理程序本身的系統時間,與真實 (牆上時鐘) 時間和子處理程序所花費的時間相反。不接受小於 0.1 秒 (例如,-0.01 作為計數會導致執行時期發生致命例外)。
請注意,CPU 秒數是最少時間:CPU 排程和其他作業系統因素可能會使嘗試複雜化,導致花費更多一點時間。不過,基準輸出也會顯示 $code
執行/秒的次數,這應該會比實際花費的秒數更有趣。
傳回 Benchmark 物件。
CODEHASHREF 是對雜湊的參照,其中包含名稱作為鍵,以及對每個值的字串以評估或程式碼參照。對於 CODEHASHREF 中的每個 (KEY, VALUE) 配對,此常式會呼叫
timethis(COUNT, VALUE, KEY, STYLE)
常式會依據 KEY 的字串比較順序呼叫。
COUNT 可以為零或負數,請參閱 timethis()。
傳回 Benchmark 物件的雜湊參照,以名稱為鍵。
傳回兩個 Benchmark 時間的差異,作為 Benchmark 物件,適合傳遞給 timestr()。
傳回一個字串,以要求的 STYLE 格式化 TIMEDIFF 物件中的時間。TIMEDIFF 預期為 Benchmark 物件,類似於 timediff() 傳回的物件。
STYLE 可為「all」、「none」、「noc」、「nop」或「auto」。「all」顯示 5 個可用的時間(「wallclock」時間、使用者時間、系統時間、子項目的使用者時間和子項目的系統時間)。「noc」顯示所有時間,但兩個子項目時間除外。「nop」僅顯示 wallclock 和兩個子項目時間。「auto」(預設值)會作用為「all」,除非子項目時間皆為零,則會作用為「noc」。「none」會防止輸出。
FORMAT 是 printf(3)-style 格式規範符號(不含開頭的「%」),用於列印時間。預設值為「5.2f」。
如果您特別要求匯入下列常式,它們會匯出到您的命名空間
清除 null 迴圈 COUNT 輪的快取時間。
清除所有快取時間。
選擇性地呼叫 timethese(),然後輸出比較圖表。這
cmpthese( -1, { a => "++\$i", b => "\$i *= 2" } ) ;
會輸出類似於
Rate b a
b 2831802/s -- -61%
a 7208959/s 155% --
此圖表從最慢到最快排序,並顯示每對測試之間的百分比速度差異。
cmpthese
也可傳遞 timethese() 傳回的資料結構
$results = timethese( -1,
{ a => "++\$i", b => "\$i *= 2" } ) ;
cmpthese( $results );
以防您想要看到兩組結果。如果第一個引數是未加祝福的雜湊參照,那就是 RESULTSHASHREF;否則那就是 COUNT。
傳回對應到列的陣列參照,每列都是陣列,包含來自上述圖表的儲存格,包括標籤。這
my $rows = cmpthese( -1,
{ a => '++$i', b => '$i *= 2' }, "none" );
會傳回類似於
[
[ '', 'Rate', 'b', 'a' ],
[ 'b', '2885232/s', '--', '-59%' ],
[ 'a', '7099126/s', '146%', '--' ],
]
注意:此結果值與回傳 timethese()
結果結構的先前版本不同。如果您想要這樣,請使用上面顯示的兩個陳述式 timethese
...cmpthese
慣用語。
順便一提,請注意兩個範例之間的結果值差異;這是基準測試的典型情況。如果這是真正的基準測試,您可能需要執行更多次反覆運算。
參數:TIME 是執行 CODE 的最短時間,而 CODE 是要執行的程式碼。CODE 可以是程式碼參考或要評估的字串;無論如何,它都將在呼叫者的套件中執行。
TIME 不是負數。countit() 將執行迴圈多次,以計算 CODE 的速度,然後再執行 TIME。實際執行的時間通常會大於 TIME,這是因為系統時脈解析度,因此最好查看反覆運算次數除以您關注的時間,而不仅仅是反覆運算次數。
傳回:Benchmark 物件。
停用空迴圈計時的快取。這將強制 Benchmark 重新計算這些計時,以針對每個計時的新程式碼片段進行計時。
啟用空迴圈計時的快取。空迴圈的 COUNT 回合所花費的時間將僅針對每個不同的 COUNT 使用計算一次。
將兩個 Benchmark 時間的總和傳回,作為適合傳遞給 timestr() 的 Benchmark 物件。
如果已安裝 Time::HiRes 模組,您可以為 Benchmark 指定特殊標籤 :hireswallclock
(如果 Time::HiRes 不可用,則標籤將被靜默忽略)。此標籤將導致以微秒為單位測量時鐘時間,而不是整數秒。但請注意,速度計算仍以 CPU 時間進行,而不是時鐘時間。
此模組中的許多函數傳回 Benchmark 物件,或者在 timethese()
的情況下,傳回雜湊的參考,其值為 Benchmark 物件。如果您想要儲存或進一步處理 Benchmark 函數的結果,這會很有用。
在內部,Benchmark 物件會保留計時值,如下面的 "NOTES" 所述。可以使用下列方法來存取它們
主體 (父) 程序的總 CPU (使用者 + 系統)。
任何子程序的總 CPU(使用者 + 系統)。
父程序和任何子程序的總 CPU。
真實經過時間「時鐘秒數」。
執行的迭代次數。
以下說明 Benchmark 物件的使用方式
$result = timethis(100000, sub { ... });
print "total CPU = ", $result->cpu_a, "\n";
資料儲存為 time 和 times 函數的值清單
($real, $user, $system, $children_user, $children_system, $iters)
以秒為單位計算整個迴圈(未除以回合數)。
計時使用 time(3) 和 times(3)。
程式碼在呼叫者的套件中執行。
空迴圈的時間(回合數相同但迴圈主體為空的迴圈)會從真實迴圈的時間中減去。
空迴圈時間可以快取,關鍵是回合數。快取可以使用類似以下的呼叫控制
clearcache($key);
clearallcache();
disablecache();
enablecache();
預設關閉快取,因為它(通常會稍微)降低準確度,而且通常不會明顯影響執行時間。
例如,
use Benchmark qw( cmpthese ) ;
$x = 3;
cmpthese( -5, {
a => sub{$x*$x},
b => sub{$x**2},
} );
輸出類似以下內容
Benchmark: running a, b, each for at least 5 CPU seconds...
Rate b a
b 1559428/s -- -62%
a 4152037/s 166% --
而
use Benchmark qw( timethese cmpthese ) ;
$x = 3;
$r = timethese( -5, {
a => sub{$x*$x},
b => sub{$x**2},
} );
cmpthese $r;
輸出類似以下內容
Benchmark: running a, b, each for at least 5 CPU seconds...
a: 10 wallclock secs ( 5.14 usr + 0.13 sys = 5.27 CPU) @ 3835055.60/s (n=20210743)
b: 5 wallclock secs ( 5.41 usr + 0.00 sys = 5.41 CPU) @ 1574944.92/s (n=8520452)
Rate b a
b 1574945/s -- -59%
a 3835056/s 144% --
Benchmark 沒有繼承其他類別,當然除了 Exporter 之外。
比較已評估的字串和程式碼參考會產生不準確的結果:程式碼參考會顯示比等效已評估字串稍慢的執行時間。
真實時間計時使用 time(2),因此粒度僅為一秒。
短測試可能會產生負數,因為 Perl 執行空迴圈的時間似乎比短測試長;請嘗試
timethis(100,'1');
空迴圈的系統時間可能略長於執行實際程式碼的迴圈的系統時間,因此差異可能最終會小於 0。
Devel::NYTProf - Perl 程式碼剖析器
Jarkko Hietaniemi <jhi@iki.fi>、Tim Bunce <Tim.Bunce@ig.co.uk>
1994 年 9 月 8 日;Tim Bunce。
1997 年 3 月 28 日;Hugo van der Sanden:新增對程式碼參考和已記錄的「偵錯」方法的支援;改寫文件。
1997 年 4 月 4 日至 7 日:Jarkko Hietaniemi,新增執行一段時間的功能。
1999 年 9 月;Barrie Slaymaker:數學修正,以及準確度和效率調整。新增 cmpthese()。現在會從 timethese() 傳回結果。公開 countit()(為 runfor())。
2001 年 12 月;Nicholas Clark:讓 timestr() 辨識「none」樣式並傳回空字串。如果 cmpthese 呼叫 timethese,讓它傳入樣式。(因此「none」會抑制輸出)。讓 sub new 將其偵錯輸出傾印到 STDERR,以與其他所有內容一致。在撰寫回歸測試時發現的所有錯誤。
2002 年 9 月,由 Jarkko Hietaniemi:新增 ':hireswallclock' 特殊標籤。
2004 年 2 月,由 Chia-liang Kao:當樣式為 'nop' 時,讓 cmpthese 和 timestr 使用子項的時間統計資料,而非父項。
2007 年 11 月,由 Christophe Grosjean:讓 cmpthese 和 timestr 計算時間與樣式參數一致,預設值不再是 'noc',而是 'all'。