Níže uvedenou třídu jsem používal delší dobu pro jednoduché měření toho jak dlouho trvá vykonávání jisté části kódu. A musím říci že až dodnes jsem měřil špatně. Problém byl v tom že jsem neměřil pouze to co jsem potřeboval ale ještě něco navíc.
Pokud se podíváte na kód třídy tak si určitě všimnete atributu [SuppressUnmanagedCodeSecurity] který je aplikován při deklaraci P\Invoke metod. Bez tohoto atributu se pří každém přechodu z managed do unmanaged provádí procházení zásobníku aby framework ověřil že všichni volající mají oprávnění volat unmanaged kód. Takže naměřený čas obsahoval i toto procházení zásobníku. Attribut [SuppressUnmanagedCodeSecurity] redukuje bezpečnostní kontrolu tím že uprávnění volat unmanaged kód se kontroluje pouze v době linkování (JIT). Takže musíte nechat třídu StopWatch "zahořet" tím že aspoň jednou zavoláte metody Stop() a Start() před vlastním měřením. Tím dojde ke zkompilování těchto metod a pak již můžete měřit trošku přesněji.
using System;
using System.Text;
using System.Security;
using System.Diagnostics;
using System.Runtime.InteropServices;
public class StopWatch
{
private long m_Start;
private long m_Finish;
private long m_Frequency;
[DllImport("kernel32.dll")]
[SuppressUnmanagedCodeSecurity]
extern private static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
[SuppressUnmanagedCodeSecurity]
extern private static short QueryPerformanceFrequency(ref long x);
public StopWatch()
{
Reset();
}
public void Start()
{
QueryPerformanceFrequency(ref m_Frequency);
QueryPerformanceCounter(ref m_Start);
}
public void Stop()
{
QueryPerformanceCounter(ref m_Finish);
}
public void Reset()
{
m_Start = 0;
m_Finish = 0;
m_Frequency = Int32.MaxValue;
}
public double Duration
{
get
{
return (m_Finish - m_Start) * 1.0 / m_Frequency;
}
}
}