'u çağırırken CLR'den benden daha hızlı nasıl şaşırtıcı bir şey bulduğumda (bana) farklı bir zaman damgası oluşturma yöntemlerini test ettim. Windows'un GetSystemTimeAsFileTime
kullanarak P çağrılmasıWindows API
/Invoke dahili aynı GetSystemTimeAsFileTime
için CLR'nin sarıcı kullanır DateTime.UtcNow
arayarak yaklaşık 3 kat daha yavaştır.
Bu nasıl olabilir?
İşte DateTime.UtcNow
's implementation var:
public static DateTime UtcNow {
get {
long ticks = 0;
ticks = GetSystemTimeAsFileTime();
return new DateTime(((UInt64)(ticks + FileTimeOffset)) | KindUtc);
}
}
[MethodImplAttribute(MethodImplOptions.InternalCall)] // Implemented by the CLR
internal static extern long GetSystemTimeAsFileTime();
çekirdek CLR en wrapper for GetSystemTimeAsFileTime
:
FCIMPL0(INT64, SystemNative::__GetSystemTimeAsFileTime)
{
FCALL_CONTRACT;
INT64 timestamp;
::GetSystemTimeAsFileTime((FILETIME*)×tamp);
#if BIGENDIAN
timestamp = (INT64)(((UINT64)timestamp >> 32) | ((UINT64)timestamp << 32));
#endif
return timestamp;
}
FCIMPLEND;
Testim kodu BenchmarkDotNet kullanan:
public class Program
{
static void Main() => BenchmarkRunner.Run<Program>();
[Benchmark]
public DateTime UtcNow() => DateTime.UtcNow;
[Benchmark]
public long GetSystemTimeAsFileTime()
{
long fileTime;
GetSystemTimeAsFileTime(out fileTime);
return fileTime;
}
[DllImport("kernel32.dll")]
public static extern void GetSystemTimeAsFileTime(out long systemTimeAsFileTime);
}
Ve sonuç:
Method | Median | StdDev |
------------------------ |----------- |---------- |
GetSystemTimeAsFileTime | 14.9161 ns | 1.0890 ns |
UtcNow | 4.9967 ns | 0.2788 ns |
CLR doğrudan arayabilirsiniz: Ayrıca ben Voigt olarak
unsafe
kullanılarakyarıya tekrar getiriyor önerdi. Pinvoke, marshalling katmanından geçer. –
@DavidHeffernan, parametrelerin sıralı olmasına gerek kalmasa bile mi? – i3arnon
@ i3arnon: Bir şeyin bunları kanıtlamak için analiz etmesi gerekiyor. –