我正嘗試構建一個小型基準測試應用程序,它允許用戶測量程序的執行時間和內存使用情況。使用C#測量其他進程的執行時間,奇數結果
這是衡量執行時間的代碼:
private static Stopwatch _stopwatch;
static void Main(string[] args]
{
_stopwatch = new Stopwatch();
//only for this test
Console.WriteLine(TimeProcess("Empty.exe"));
Console.WriteLine(TimeProcess("Sieve.exe"));
Console.ReadKey();
}
private static long TimeProcess(String name)
{
Process process = new Process();
process.StartInfo.FileName = name;
_stopwatch.Reset();
_stopwatch.Start();
process.Start();
process.WaitForExit();
_stopwatch.Stop();
return _stopwatch.ElapsedMilliseconds;
}
要查看代碼是否工作正常,我決定實施「埃拉托色尼的篩」算法。我實施了兩次,一次使用內置秒錶,還有一次沒有。
篩
int[] numbersToTest = Enumerable.Range(0, 1000).ToArray();
int posInArray = 2;
while (numbersToTest[posInArray] != numbersToTest[numbersToTest.Length - 1])
{
numbersToTest = numbersToTest.Where(x => x % numbersToTest[posInArray] != 0 || x == numbersToTest[posInArray]).ToArray();
posInArray++;
}
TimedSieve:
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int[] numbersToTest = Enumerable.Range(0, 1000).ToArray();
int posInArray = 2;
while (numbersToTest[posInArray] != numbersToTest[numbersToTest.Length - 1])
{
numbersToTest = numbersToTest.Where(x => x % numbersToTest[posInArray] != 0 || x == numbersToTest[posInArray]).ToArray();
posInArray++;
}
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedTicks);
而且,我有一個空的主要方法的項目。我的邏輯是,當我測量「Sieve」的執行並減去空項目的時間時,結果數字應該與「TimedSieve」所測量的數字大致相同。 於是我開始測量......
Empty: 79 milliseconds
Sieve: 53 milliseconds
TimedSieve: 4 milliseconds
顯然,這些結果似乎很腥:
- 的TimedSieve是很多比這兩個空項目和篩
- 空項目是慢速度更快比篩子!
只是出於好奇,我也定時篩和使用Powershells「措施命令」
Sieve: 25 milliseconds
Empty: 17 milliseconds
東西我注意到的是空項目的順序進行測量的過程影響的事實結果,首先測量的過程總是失敗。我也注意到,過程是這樣
process.Start();
_stopwatch.Start();
開始後移動秒錶開始擺脫了上述效果(空現在總是比篩快),並生產出更接近一個很大的數字的其它測量方法
Empty: 34
Sieve: 42
在試圖解決這個問題的結果,我也讀了基準測試應包括一個「熱身」輪,我決定基準這兩個程序多次,取平均值,以取得更好的成績。
static void Main(string[] args)
{
_stopwatch = new Stopwatch();
//discard results of the first run
TimeProcess("Sieve.exe");
long sum = 0;
for (int i = 0; i < 100; i++)
{
sum += TimeProcess("Sieve.exe");
}
Console.WriteLine(sum/100);
TimeProcess("Empty.exe");
sum = 0;
for (int i = 0; i < 100; i++)
{
sum += TimeProcess("Empty.exe");
}
Console.WriteLine(sum/100);
Console.ReadKey();
}
這擺脫了「空比篩慢」的效果,這也是爲什麼我決定重新開始的過程之前秒錶。
如何改進此代碼以獲得可靠的結果?雖然這些數字變得更加合理,但它們仍然比Powershell和TimedSieve測量結果都要慢。
您可能在那裏測量磁盤IO時間,這就是爲什麼結果很可疑。第一個過程比較慢,因爲磁盤需要尋找,而第二個過程很可能已經找到了,並且剛剛進入。不幸的是,沒有簡單的方法來消除這種影響。第二個解決方案(啓動一次,然後運行100次)的原因是Windows將程序緩存到內存中。如果緩存不受干擾(就像在這種情況下那樣),那麼它只能從緩存中加載程序。 –
謝謝,這似乎是對第一個結果的合理解釋,我懷疑它會進入我的腦海 – Aifu
這是一個經常被忽視的解釋,有時我們忘記了(我們所有的程序員,甚至)還有其他事情正在進行在節目的開始。磁盤文件IO,內存分配,堆分配等等。 –