Freigeben über


Abrufen von hochauflösenden Zeitstempeln

Windows stellt APIs bereit, mit denen Sie hochauflösende Zeitstempel abrufen oder Zeitintervalle messen können. Die primäre API für nativen Code ist QueryPerformanceCounter (QPC). Bei Gerätetreibern ist die Kernelmodus-API KeQueryPerformanceCounter. Für verwalteten Code verwendet die System.Diagnostics.Stopwatch-KlasseQPC als genaue Zeitbasis.

QPC ist unabhängig von und wird nicht mit externen Zeitverweisen synchronisiert. Verwenden Sie GetSystemTimePreciseAsFileTime, um Zeitstempel abzurufen, die mit einem externen Zeitverweis synchronisiert werden können, z. B. Koordinierte Universelle Zeit (Coordinated Universal Time, UTC).

Zeitstempel und Zeitintervallmessungen sind ein integraler Bestandteil von Computer- und Netzwerkleistungsmessungen. Zu diesen Leistungsmessoperationen gehören die Berechnung der Antwortzeit, des Durchsatzes und der Latenz sowie das Profiling der Codeausführung. Jeder dieser Vorgänge umfasst eine Messung von Aktivitäten, die während eines Zeitintervalls auftreten, das durch ein Start- und ein Endereignis definiert wird und unabhängig von einer externen Tageszeit-Referenz sein kann.

QPC ist in der Regel die beste Methode, um Zeitstempelereignisse zu verwenden und kleine Zeitintervalle zu messen, die auf demselben System oder virtuellen Computer auftreten. Erwägen Sie die Verwendung von GetSystemTimePreciseAsFileTime , wenn Sie Zeitstempelereignisse auf mehreren Computern durchführen möchten, vorausgesetzt, jeder Computer nimmt an einem Zeitsynchronisierungsschema teil, z. B. Network Time Protocol (NTP). QPC hilft Ihnen, Probleme zu vermeiden, die mit anderen Zeitmessungsansätzen auftreten können, z. B. das direkte Lesen des Zeitstempelzählers (TSC) des Prozessors.

QPC-Unterstützung in Windows-Versionen

QPC wurde in Windows 2000 und Windows XP eingeführt und hat sich weiterentwickelt, um die Verbesserungen der Hardwareplattform und -prozessoren zu nutzen. Hier beschreiben wir die Merkmale von QPC auf verschiedenen Windows-Versionen, um Ihnen bei der Verwaltung von Software zu helfen, die auf diesen Windows-Versionen ausgeführt wird.

Windows XP und Windows 2000

QPC ist unter Windows XP und Windows 2000 verfügbar und funktioniert gut auf den meisten Systemen. Das BIOS einiger Hardwaresysteme gab nicht korrekt an, welche Hardware-CPU-Merkmale vorhanden waren (insbesondere ob ein nicht-invarianter TSC vorlag). Zudem verwendeten einige Multi-Core- oder Multiprozessorsysteme Prozessoren mit TSCs, die nicht über alle Kerne hinweg synchronisiert werden konnten. Systeme mit fehlerhafter Firmware, die diese Versionen von Windows ausführen, bieten möglicherweise nicht den gleichen QPC-Wert auf verschiedenen Kernen, wenn sie den TSC als Grundlage für QPC verwendet haben.

Windows Vista und Windows Server 2008

Alle Computer, die mit Windows Vista und Windows Server 2008 ausgeliefert wurden, verwendeten einen Plattformzähler (High Precision Event Timer (HPET)) oder den ACPI Power Management Timer (PM Timer) als Basis für QPC. Solche Plattformtimer haben eine höhere Zugriffslatenz als der TSC und werden zwischen mehreren Prozessoren gemeinsam genutzt. Dies beschränkt die Skalierbarkeit von QPC , wenn sie gleichzeitig von mehreren Prozessoren aufgerufen wird.

Windows 7 und Windows Server 2008 R2

Die meisten Windows 7- und Windows Server 2008 R2-Computer verfügen über Prozessoren mit tsCs mit konstanter Rate und verwenden diese Indikatoren als Grundlage für QPC. TSCs sind hochauflösende Hardwarezähler pro Prozessor, auf die mit sehr geringer Latenz und minimalem Overhead zugegriffen werden kann (abhängig vom Prozessortyp in einer Größenordnung von 10er oder 100er Computerzyklen). Windows 7 und Windows Server 2008 R2 verwenden TSCs als Basis von QPC auf Systemen mit einer einzelnen Takt-Domäne, bei denen das Betriebssystem (oder der Hypervisor) die einzelnen TSCs während der Systeminitialisierung genau synchronisieren kann. Auf solchen Systemen ist die Lesekosten des Leistungsindikators im Vergleich zu Systemen, die einen Plattformzähler verwenden, deutlich niedriger. Darüber hinaus gibt es keinen zusätzlichen Aufwand für gleichzeitige Anrufe und Abfragen im Benutzermodus umgehen häufig Systemaufrufe, wodurch der Aufwand weiter reduziert wird. Auf Systemen, bei denen der TSC nicht zum Timekeeping geeignet ist, wählt Windows automatisch einen Plattformzähler (entweder den HPET-Timer oder den ACPI PM-Timer) als Basis für QPC aus.

Windows 8, Windows 8.1, Windows Server 2012 und Windows Server 2012 R2

Windows 8, Windows 8.1, Windows Server 2012 und Windows Server 2012 R2 verwenden TSCs als Grundlage für den Leistungsindikator. Der TSC-Synchronisierungsalgorithmus wurde erheblich verbessert, um große Systeme mit vielen Prozessoren besser aufzunehmen. Darüber hinaus wurde Unterstützung für die neue präzise Time-of-Day-API hinzugefügt, die das Abrufen präziser Zeitstempel aus dem Betriebssystem ermöglicht. Weitere Informationen finden Sie unter GetSystemTimePreciseAsFileTime. Auf Windows RT- und Windows 11- und Windows 10-Geräten mit Arm-Prozessoren basiert der Leistungsindikator entweder auf einem proprietären Plattformzähler oder dem Vom Arm Generic Timer bereitgestellten Systemzähler, wenn die Plattform so ausgestattet ist.

Leitfaden zum Abrufen von Zeitstempeln

Windows hat und wird weiterhin in die Bereitstellung eines zuverlässigen und effizienten Leistungsindikators investieren. Wenn Sie Zeitstempel mit einer Auflösung von 1 Mikrosekunden oder besser benötigen und die Zeitstempel nicht mit einem externen Zeitverweis synchronisiert werden müssen, wählen Sie QueryPerformanceCounter, KeQueryPerformanceCounter oder KeQueryInterruptTimePrecise aus. Wenn Sie UTC-synchronisierte Zeitstempel mit einer Auflösung von 1 Mikrosekunden oder besser benötigen, wählen Sie "GetSystemTimePreciseAsFileTime " oder "KeQuerySystemTimePrecise" aus.

Bei einer relativ geringen Anzahl von Plattformen, die das TSC-Register nicht als QPC-Basis verwenden können, z. B. aus Gründen, die in Hardwaretimerinformationen erläutert werden, kann das Abrufen von Zeitstempeln mit hoher Auflösung wesentlich teurer sein als das Abrufen von Zeitstempeln mit geringerer Auflösung. Wenn die Auflösung von 10 bis 16 Millisekunden ausreicht, können Sie GetTickCount64, QueryInterruptTime, QueryUnbiasedInterruptTime, KeQueryInterruptTime oder KeQueryUnbiasedInterruptTime verwenden, um Zeitstempel abzurufen, die nicht mit einem externen Zeitverweis synchronisiert werden. Verwenden Sie für UTC-synchronisierte Zeitstempel GetSystemTimeAsFileTime oder KeQuerySystemTime. Wenn eine höhere Auflösung erforderlich ist, können Sie stattdessen QueryInterruptTimePrecise, QueryUnbiasedInterruptTimePrecise oder KeQueryInterruptTimePrecise verwenden, um stattdessen Zeitstempel abzurufen.

Im Allgemeinen sind die Leistungsindikatorenergebnisse in allen Prozessoren in Multi-Core- und Multiprozessorsystemen konsistent, auch wenn sie in verschiedenen Threads oder Prozessen gemessen werden. Hier sind einige Ausnahmen für diese Regel:

  • Betriebssystemen vor Windows Vista, die auf bestimmten Prozessoren ausgeführt werden, können aus einem der folgenden Gründe gegen diese Konsistenz verstoßen:

    • Die Hardwareprozessoren weisen einen nicht invarianten TSC auf, und das BIOS gibt diese Bedingung nicht richtig an.
    • Der verwendete TSC-Synchronisierungsalgorithmus war für Systeme mit einer großen Anzahl von Prozessoren nicht geeignet.
  • Wenn Sie Leistungszählerergebnisse vergleichen, die aus verschiedenen Threads abgerufen werden, sollten Werte, die sich um ± 1 Tick unterscheiden, als mehrdeutig betrachtet werden. Wenn die Zeitstempel aus demselben Thread stammen, gilt diese ± 1 Teilstrichunsicherheit nicht. In diesem Zusammenhang bezieht sich der Begriff Tick auf einen Zeitraum, der 1 ÷ (die Frequenz des von QueryPerformanceFrequency abgerufenen Leistungszählers) entspricht.

Wenn Sie den Leistungsindikator auf großen Serversystemen mit nicht synchronisierten Domänen mit mehreren Takten verwenden, ermittelt Windows, dass der TSC nicht für Zeitplanungszwecke verwendet werden kann, und wählt einen Plattformzähler als Basis für QPC aus. Obwohl dieses Szenario weiterhin zuverlässige Zeitstempel liefert, ist die Zugriffslatenz und Skalierbarkeit negativ betroffen. Verwenden Sie daher, wie bereits in der vorstehenden Verwendungsanleitung erwähnt, nur die APIs, die 1 Mikrosekunden oder eine bessere Auflösung bereitstellen, wenn eine solche Auflösung erforderlich ist. Der TSC wird als Grundlage für QPC in Systemen mit mehreren Taktdomänen verwendet, die die Hardwaresynchronisierung aller Prozessor-Taktdomänen umfassen, sodass sie effektiv als ein einzelnes Taktdomänensystem fungieren.

Die Häufigkeit des Leistungsindikators wird beim Systemstart festgelegt und ist für alle Prozessoren konsistent, sodass Sie nur die Häufigkeit von QueryPerformanceFrequency als Initialisierung der Anwendung abfragen und dann das Ergebnis zwischenspeichern müssen.

Virtualisierung

Es wird erwartet, dass der Leistungszähler zuverlässig auf allen virtuellen Gastmaschinen funktioniert, die auf ordnungsgemäß implementierten Hypervisoren betrieben werden. Hypervisoren, die der Hypervisor-Version 1.0-Schnittstelle entsprechen und die Referenzzeiterleuchtung anzeigen, können jedoch erheblich geringeren Aufwand bieten. Weitere Informationen zu Hypervisorschnittstellen und -erleuchtungen finden Sie unter Hypervisorspezifikationen.

Direkte TSC-Verwendung

Es wird dringend davon abgeraten, die RDTSC oder RDTSCP Prozessoranweisungen zu verwenden, um den TSC direkt abzufragen, da die Ergebnisse unter einigen Windows-Versionen, bei Livemigrationen virtueller Maschinen und auf Hardware-Systemen ohne invariante oder eng synchronisierte TSCs nicht zuverlässig sind. Stattdessen empfehlen wir Ihnen, QPC zu verwenden, um die von ihr angebotene Abstraktion, Konsistenz und Portabilität zu nutzen.

Beispiele für den Erwerb von Zeitstempeln

Die verschiedenen Codebeispiele in diesen Abschnitten zeigen, wie Zeitstempel erworben werden.

Verwenden von QPC im systemeigenen Code

In diesem Beispiel wird gezeigt, wie QPC in C- und C++-systemeigenem Code verwendet wird.

LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
LARGE_INTEGER Frequency;

QueryPerformanceFrequency(&Frequency); 
QueryPerformanceCounter(&StartingTime);

// Activity to be timed

QueryPerformanceCounter(&EndingTime);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;


//
// We now have the elapsed number of ticks, along with the
// number of ticks-per-second. We use these values
// to convert to the number of elapsed microseconds.
// To guard against loss-of-precision, we convert
// to microseconds *before* dividing by ticks-per-second.
//

ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;

Abrufen von Zeitstempeln mit hoher Auflösung aus verwaltetem Code

In diesem Beispiel wird die Verwendung der System.Diagnostics.Stopwatch-Klasse mit verwaltetem Code veranschaulicht.

using System.Diagnostics;

long StartingTime = Stopwatch.GetTimestamp();

// Activity to be timed

long EndingTime  = Stopwatch.GetTimestamp();
long ElapsedTime = EndingTime - StartingTime;

double ElapsedSeconds = ElapsedTime * (1.0 / Stopwatch.Frequency);

Die System.Diagnostics.Stopwatch-Klasse bietet auch mehrere bequeme Methoden zum Ausführen von Zeitintervallmessungen.

Verwenden von QPC aus dem Kernelmodus

Der Windows-Kernel ermöglicht den Kernelmoduszugriff auf den Leistungsindikator über KeQueryPerformanceCounter , aus dem sowohl der Leistungsindikator als auch die Leistungshäufigkeit abgerufen werden können. KeQueryPerformanceCounter ist nur im Kernelmodus verfügbar und wird für Autoren von Gerätetreibern und anderen Kernelmoduskomponenten bereitgestellt.

In diesem Beispiel wird gezeigt, wie KeQueryPerformanceCounter im C- und C++-Kernelmodus verwendet wird.

LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
LARGE_INTEGER Frequency;

StartingTime = KeQueryPerformanceCounter(&Frequency);

// Activity to be timed

EndingTime = KeQueryPerformanceCounter(NULL);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;

Allgemeine Häufig gestellte Fragen zu QPC und TSC

Hier finden Sie Antworten auf häufig gestellte Fragen zu QPC und TSCs im Allgemeinen.

Ist QueryPerformanceCounter() mit der Funktion Win32 GetTickCount() oder GetTickCount64() identisch?

Nein. GetTickCount und GetTickCount64 beziehen sich nicht auf QPC. GetTickCount und GetTickCount64 geben die Anzahl von Millisekunden zurück, seit das System gestartet wurde.

Sollte ich QPC verwenden oder die RDTSC/RDTSCP-Anweisungen direkt aufrufen?

Um Fehler und Portabilitätsprobleme zu vermeiden, empfehlen wir Ihnen dringend, QPC anstelle des TSC-Registers oder der RDTSC - oder RDTSCP-Prozessoranweisungen zu verwenden.

Was ist die Beziehung von QPC zu einer epochen externen Zeit? Kann es mit einer externen Epoche wie UTC synchronisiert werden?

QPC basiert auf einem Hardwarezähler, der nicht mit einem externen Zeitverweis wie UTC synchronisiert werden kann. ** Verwenden Sie für präzise Tageszeit-Zeitstempel, die an eine externe UTC-Referenz synchronisiert werden können, GetSystemTimePreciseAsFileTime.

Ist QPC von Sommerzeit, Schaltsekunden, Zeitzonen oder Systemzeitänderungen betroffen, die vom Administrator vorgenommen wurden?

Nein. QPC ist vollständig unabhängig von der Systemzeit und UTC.

Wird die QPC-Genauigkeit durch Prozessorfrequenzänderungen durch Energiemanagement oder Turbo Boost-Technologie beeinflusst?

Nein. Wenn der Prozessor über einen invarianten TSC verfügt, ist das QPC nicht von diesen Änderungen betroffen. Wenn der Prozessor keinen invarianten TSC hat, wird QPC auf einen Plattformhardwaretimer zurückgesetzt, der von Prozessorfrequenzänderungen oder Turbo Boost-Technologie nicht betroffen ist.

Funktioniert QPC zuverlässig auf Multiprozessorsystemen, Multi-Core-Systemen und Systemen mit Hyperthreading?

Ja.

Wie kann ich feststellen und überprüfen, ob QPC auf meinem Computer funktioniert?

Sie müssen diese Prüfungen nicht durchführen.

Welche Prozessoren haben nicht invariante TSCs? Wie kann ich überprüfen, ob mein System über einen nicht invarianten TSC verfügt?

Sie müssen diese Prüfung nicht selbst durchführen. Windows-Betriebssysteme führen mehrere Überprüfungen bei der Systeminitialisierung durch, um festzustellen, ob der TSC als Grundlage für QPC geeignet ist. Für die Referenzzwecke können Sie jedoch ermitteln, ob Ihr Prozessor über einen invarianten TSC verfügt, indem Sie eine der folgenden verwenden:

  • das Coreinfo.exe Hilfsprogramm von Windows Sysinternals
  • Überprüfen der von der CPUID-Anweisung zurückgegebenen Werte im Zusammenhang mit den TSC-Merkmalen
  • Dokumentation des Prozessorherstellers

Im Folgenden finden Sie die TSC-INVARIANT Informationen, die vom Windows Sysinternals Coreinfo.exe Hilfsprogramm (www.sysinternals.com) bereitgestellt werden. Ein Sternchen bedeutet "True".

> Coreinfo.exe 

Coreinfo v3.2 - Dump information on system CPU and memory topology
Copyright (C) 2008-2012 Mark Russinovich
Sysinternals - www.sysinternals.com

 <unrelated text removed>

RDTSCP          * Supports RDTSCP instruction
TSC             * Supports RDTSC instruction
TSC-DEADLINE    - Local APIC supports one-shot deadline timer
TSC-INVARIANT   * TSC runs at constant rate

Funktioniert QPC zuverlässig auf Windows RT-Hardwareplattformen?

Ja.

Wie oft wird QPC überrollt?

Nicht weniger als 100 Jahre ab dem letzten Systemstart und potenziell länger basierend auf dem zugrunde liegenden Hardwarezeitgeber. Bei den meisten Anwendungen ist ein Rollover kein Problem.

Was ist die Rechenkosten für das Aufrufen von QPC?

Die Berechnungskosten von QPC werden hauptsächlich durch die zugrunde liegende Hardwareplattform bestimmt. Wenn das TSC-Register als Grundlage für QPC verwendet wird, werden die Berechnungskosten in erster Linie durch die Zeit bestimmt, die der Prozessor benötigt, um eine RDTSC-Anweisung auszuführen. Diese Zeit reicht von 10 CPU-Zyklen bis zu mehreren hundert CPU-Zyklen, je nach verwendetem Prozessor. Wenn der TSC nicht verwendet werden kann, wählt das System eine andere Hardwarezeitbasis aus. Da sich diese Zeitbasen auf der Hauptplatine befinden (z. B. auf der PCI South Bridge oder PCH), ist die Berechnungskosten pro Anruf höher als der TSC und liegt häufig in der Nähe von 0,8 - 1,0 Mikrosekunden je nach Prozessorgeschwindigkeit und anderen Hardwarefaktoren. Diese Kosten werden von der Zeit dominiert, die für den Zugriff auf das Hardwaregerät auf dem Motherboard erforderlich ist.

Erfordert QPC einen Kernelübergang (Systemaufruf)?

Ein Kernelübergang ist nicht erforderlich, wenn das System das TSC-Register als Basis für QPC verwenden kann. Wenn das System eine andere Zeitbasis verwenden muss, z. B. den HPET- oder PM-Timer, ist ein Systemaufruf erforderlich.

Ist der Leistungsindikator monoton (nicht abnehmend)?

Ja. QPC geht nicht rückwärts.

Kann der Leistungsindikator verwendet werden, um Ereignisse rechtzeitig zu ordnen?

Ja. Beim Vergleichen von Leistungszählerergebnissen, die aus verschiedenen Threads abgerufen wurden, weisen jedoch Werte, die sich um ± 1 Tick unterscheiden, eine mehrdeutige Sortierung auf, ähnlich wie bei identischen Zeitstempeln.

Wie genau ist der Leistungsindikator?

Die Antwort hängt von einer Vielzahl von Faktoren ab. Weitere Informationen finden Sie unter Eigenschaften der Hardware-Uhr auf niedriger Ebene.

Häufig gestellte Fragen zur Programmierung mit QPC und TSC

Hier finden Sie Antworten auf häufig gestellte Fragen zur Programmierung mit QPC und TSCs.

Ich muss die QPC-Ausgabe in Millisekunden konvertieren. Wie kann ich mit der Konvertierung in "Double" oder "Float" einen Genauigkeitsverlust vermeiden?

Beachten Sie beim Ausführen von Berechnungen für ganzzahlige Leistungsindikatoren mehrere Punkte:

  • Ganzzahldivision verliert den Rest. Dies kann in einigen Fällen zu einem Genauigkeitsverlust führen.
  • Die Konvertierung zwischen 64-Bit-Ganzzahlen und Gleitkomma (Double) kann zu Einem Genauigkeitsverlust führen, da die Gleitkomma-Mantissa nicht alle möglichen integralen Werte darstellen kann.
  • Multiplikation von 64-Bit-Ganzzahlen kann zu einem ganzzahligen Überlauf führen.

Generell sollten diese Berechnungen und Umwandlungen so lange wie möglich hinausgezögert werden, um die Akkumulation von Fehlern zu vermeiden.

Wie kann ich QPC in 100 Nanosekunden-Teilstriche konvertieren, damit ich ihn zu einer FILETIME hinzufügen kann?

Eine Dateizeit ist ein 64-Bit-Wert, der die Anzahl von 100-Nanosekundenintervallen darstellt, die seit dem 12.00. Januar 1601 koordinierte Weltzeit (UTC) verstrichen sind. Dateizeiten werden von Win32-API-Aufrufen verwendet, die Tageszeit zurückgeben, z. B. GetSystemTimeAsFileTime und GetSystemTimePreciseAsFileTime. Im Gegensatz dazu gibt QueryPerformanceCounter Werte zurück, die Zeit in Einheiten von 1/(die Häufigkeit des von QueryPerformanceFrequency abgerufenen Leistungsindikators) darstellen. Die Konvertierung zwischen den beiden erfordert die Berechnung des Verhältnisses des QPC-Intervalls und der Intervalle von 100-Nanosekunden. Achten Sie darauf, keine Genauigkeit zu verlieren, da die Werte möglicherweise klein sind (0,0000001 / 0,000000340).

Warum wird der Zeitstempel, der von QPC zurückgegeben wird, eine signierte ganze Zahl zurückgegeben?

Berechnungen, die QPC-Zeitstempel umfassen, können Subtraktion umfassen. Mithilfe eines signierten Werts können Sie Berechnungen behandeln, die negative Werte liefern können.

Wie erhalte ich Zeitstempel mit hoher Auflösung aus verwaltetem Code?

Rufen Sie die Stopwatch.GetTimeStamp-Methode aus der System.Diagnostics.Stopwatch-Klasse auf. Ein Beispiel zur Verwendung von Stopwatch.GetTimeStamp finden Sie unter dem Abschnitt Abrufen von Zeitstempeln aus verwaltetem Code mit hoher Auflösung.

Unter welchen Umständen gibt QueryPerformanceFrequency FALSE zurück, oder QueryPerformanceCounter gibt null zurück?

Dies tritt nicht auf einem System auf, das Windows XP oder höher ausführt, vorausgesetzt, Sie übergeben gültige Parameter an die Funktionen.

Muss ich die Threadaffinität auf einen einzelnen Kern festlegen, um QPC zu verwenden?

Nein. Weitere Informationen finden Sie unter Anleitungen zum Abrufen von Zeitstempeln. Dieses Szenario ist weder notwendig noch wünschenswert. Das Ausführen dieses Szenarios kann sich negativ auf die Leistung Ihrer Anwendung auswirken, indem die Verarbeitung auf einen Kern beschränkt wird oder ein Engpass für einen einzelnen Kern entsteht, wenn mehrere Threads ihre Affinität beim Aufrufen von QueryPerformanceCounter auf denselben Kern festlegen.

Hardwareuhreigenschaften auf niedrigerer Ebene

In diesen Abschnitten werden die Merkmale der Hardwareuhr auf niedriger Ebene angezeigt.

Absolute Uhren und Differenzuhren

Absolute Uhren bieten genaue Tageszeitwerte. Sie basieren in der Regel auf koordinierter Weltzeit (COORDINATED Universal Time, UTC), und folglich hängt ihre Genauigkeit teilweise davon ab, wie gut sie mit einem externen Zeitverweis synchronisiert werden. Differenzuhren messen Zeitintervalle und basieren typischerweise nicht auf einer externen Zeitepoche. QPC ist eine Differenzuhr und wird nicht mit einer externen Zeitepoche oder Referenz synchronisiert. Wenn Sie QPC für Zeitintervallmessungen verwenden, erhalten Sie in der Regel eine bessere Genauigkeit als bei Verwendung von Zeitstempeln, die von einer absoluten Uhr abgeleitet werden. Dies liegt daran, dass der Prozess der Synchronisierung der Zeit einer absoluten Uhr Phasen- und Frequenzverschiebungen einführen kann, die die Unsicherheit von kurzfristigen Zeitintervallmessungen erhöhen.

Auflösung, Präzision, Genauigkeit und Stabilität

QPC verwendet einen Hardwarezähler als Grundlage. Hardwaretimer bestehen aus drei Teilen: einem Tick-Generator, einem Zähler, der die Ticks zählt, und einem Mittel zum Abrufen des Zählerwerts. Die Eigenschaften dieser drei Komponenten bestimmen die Auflösung, Genauigkeit, Genauigkeit und Stabilität von QPC.

Wenn ein Hardwaregenerator Ticks mit einer konstanten Rate bereitstellt, können Zeitintervalle durch einfaches Zählen dieser Ticks gemessen werden. Die Rate, mit der die Zecken erzeugt werden, wird als Frequenz bezeichnet und in Hertz (Hz) ausgedrückt. Der Kehrwert der Frequenz wird als Periode oder Taktintervall bezeichnet und in einer geeigneten Zeiteinheit des internationalen Einheitensystems (SI) ausgedrückt (z. B. Sekunde, Millisekunde, Mikrosekunde oder Nanosekunde).

Zeitintervall

Die Auflösung des Timers ist gleich der Periode. Die Auflösung bestimmt die Fähigkeit, zwischen zwei beliebigen Zeitstempeln zu unterscheiden, und platziert eine untere Grenze in den kleinsten Zeitintervallen, die gemessen werden können. Dies wird manchmal als Tick-Auflösung bezeichnet.

Digitale Zeitmessung führt zu einer Messunsicherheit von ± 1 Tick, da der digitale Zähler in diskreten Schritten voranschreitet, während die Zeit kontinuierlich voranschreitet. Diese Unsicherheit wird als Quantisierungsfehler bezeichnet. Bei typischen Zeitintervallmessungen kann dieser Effekt häufig ignoriert werden, da der Quantisierungsfehler wesentlich kleiner als das zu messende Zeitintervall ist.

Digitale Zeitmessung

Wenn der gemessene Zeitraum jedoch klein ist und sich der Timerauflösung nähert, müssen Sie diesen Quantisierungsfehler berücksichtigen. Die Größe des eingeführten Fehlers entspricht einer Taktperiode.

Die folgenden beiden Diagramme veranschaulichen die Auswirkungen der ± 1 Tick-Unschärfe mit einem Timer bei einer zeitlichen Auflösung von einer Einheit.

Tickunsicherheit

QueryPerformanceFrequency gibt die Frequenz von QPC zurück, und die Periode sowie die Auflösung entsprechen dem Kehrwert dieses Werts. Die Von QueryPerformanceFrequency zurückgegebene Leistungsindikatorhäufigkeit wird während der Systeminitialisierung bestimmt und ändert sich nicht, während das System ausgeführt wird.

Hinweis

Häufig gibt QueryPerformanceFrequency nicht die tatsächliche Häufigkeit des Hardware-Tick-Generators zurück. In einigen älteren Versionen von Windows gibt QueryPerformanceFrequency beispielsweise die TSC-Häufigkeit dividiert durch 1024 zurück. und wenn sie unter einem Hypervisor ausgeführt wird, der die Hypervisor-Version 1.0-Schnittstelle implementiert (oder immer in einigen neueren Versionen von Windows), ist die Leistungsindikatorhäufigkeit auf 10 MHz festgelegt. Gehen Sie daher nicht davon aus, dass QueryPerformanceFrequency einen von der Hardwarehäufigkeit abgeleiteten Wert zurückgibt.

 

QueryPerformanceCounter liest den Performancezähler und gibt die Gesamtanzahl der Ticks zurück, die seit dem Start des Windows-Betriebssystems aufgetreten sind, einschließlich der Zeit, zu der sich der Computer in einem Standbyzustand befand, z. B. Standbymodus, Ruhezustand oder verbundener Standbymodus.

In diesen Beispielen wird gezeigt, wie Sie das Teilstrichintervall und die Auflösung berechnen und wie die Teilstrichanzahl in einen Zeitwert konvertiert wird.

Beispiel 1

QueryPerformanceFrequency gibt den Wert 3.125.000 auf einem bestimmten Computer zurück. Was sind das Taktintervall und die Auflösung der QPC-Messungen auf dieser Maschine? Das Tick-Intervall oder die Periode ist der Kehrwert von 3,125,000, also 0,000000320 (320 Nanosekunden). Daher entspricht jeder Tick dem Verstreichen von 320 Nanosekunden. Zeitintervalle, die kleiner als 320 Nanosekunden sind, können auf diesem Computer nicht gemessen werden.

Tick-Intervall = 1/(Leistungsfrequenz)

Teilstrichintervall = 1/3,125,000 = 320 ns

Beispiel 2

Auf demselben Computer wie im vorherigen Beispiel beträgt die Differenz der von zwei aufeinander folgenden Aufrufen an QPC zurückgegebenen Werte 5. Wie viel Zeit ist zwischen den beiden Anrufen abgelaufen? 5 Ticks mal 320 Nanosekunden ergibt 1,6 Mikrosekunden.

VerstricheneZeit = Ticks * Tick-Intervall

ElapsedTime = 5 * 320 ns = 1,6 μs

Es benötigt Zeit, um auf den Tick-Zähler in der Software zuzugreifen und ihn auszulesen, und diese Zugriffszeit kann die Genauigkeit der Zeitmessung beeinträchtigen. Dies liegt daran, dass die minimale Intervallzeit (das kleinste Zeitintervall, das gemessen werden kann) entweder durch die höhere Auflösung oder die Zugriffszeit bestimmt wird, je nachdem, welche größer ist.

Precision = MAX [Auflösung, Zugriffszeit]

Betrachten Sie beispielsweise einen hypothetischen Hardwaretimer mit einer Auflösung von 100 Nanosekunden und einer 800 Nanosekunden-Zugriffszeit. Dies kann der Fall sein, wenn der Plattformtimer anstelle des TSC-Registers als Grundlage für QPC verwendet wurde. Daher wäre die Genauigkeit 800 Nanosekunden nicht 100 Nanosekunden, wie in dieser Berechnung gezeigt.

Genauigkeit = MAX [800 ns,100 ns] = 800 ns

Diese beiden Abbildungen zeigen diesen Effekt.

qpc-Zugriffszeit

Wenn die Zugriffszeit größer als die Auflösung ist, versuchen Sie nicht, die Genauigkeit zu verbessern, indem Sie erraten. Mit anderen Worten: Es ist ein Fehler, davon auszugehen, dass der Zeitstempel genau in der Mitte oder am Anfang oder am Ende des Anrufs genommen wird.

Betrachten Sie dagegen das folgende Beispiel, in dem die QPC-Zugriffszeit nur 20 Nanosekunden beträgt und die Hardwareuhrauflösung 100 Nanosekunden beträgt. Dies kann der Fall sein, wenn das TSC-Register als Grundlage für QPC verwendet wurde. Hier ist die Genauigkeit durch die Uhrauflösung begrenzt.

qpc-Genauigkeit

In der Praxis finden Sie Zeitquellen, für die die zum Lesen des Zählers erforderliche Zeit größer oder kleiner als die Auflösung ist. In beiden Fällen wird die größere von beiden Präzisionen verwendet.

Diese Tabelle enthält Informationen zur ungefähren Auflösung, Zugriffszeit und Genauigkeit einer Vielzahl von Uhren. Beachten Sie, dass einige der Werte mit unterschiedlichen Prozessoren, Hardwareplattformen und Prozessorgeschwindigkeiten variieren.

Uhrquelle Nominale Taktfrequenz Uhrauflösung Zugriffszeit (typisch) Präzision
PC RTC 64 Hz 15,625 Millisekunden N/A N/A
Abfrageleistungszähler mit TSC mit 3 GHz Prozessoruhr 3 MHz 333 Nanosekunden 30 Nanosekunden 333 Nanosekunden
RDTSC-Maschinenanweisung auf einem System mit einer 3-GHz-Zykluszeit 3 GHz 333 Picosekunden 30 Nanosekunden 30 Nanosekunden

 

Da QPC einen Hardwarezähler verwendet, erhalten Sie beim Verständnis einiger grundlegender Merkmale von Hardwarezählern Kenntnisse über die Funktionen und Einschränkungen von QPC.

Der am häufigsten verwendete Hardware-Tick-Generator ist ein Kristalloszillator. Das Kristall ist ein kleines Stück Quarz oder ein anderes Keramikmaterial, das optoelektrische Eigenschaften aufweist, die einen kostengünstigen Frequenzbezug mit hervorragender Stabilität und Genauigkeit bieten. Diese Frequenz wird verwendet, um die vom Taktgeber gezählten Impulse zu generieren.

Die Genauigkeit eines Zeitgebers bezieht sich auf den Grad der Konformität mit einem echten oder Standardwert. Dies hängt in erster Linie von der Fähigkeit des Kristalloszillators ab, Impulse mit der angegebenen Frequenz zu erzeugen. Wenn die Frequenz der Schwingung zu hoch ist, wird die Uhr "schnell laufen", und gemessene Intervalle werden länger angezeigt, als sie wirklich sind; und wenn die Häufigkeit zu niedrig ist, wird die Uhr "langsam" ausgeführt, und gemessene Intervalle werden kürzer als sie sind.

Bei typischen Zeitintervallmessungen für kurze Dauer (z. B. Antwortzeitmessungen, Netzwerklatenzmessungen usw.) ist die Genauigkeit des Hardware-Oszillators in der Regel ausreichend. Bei einigen Messungen ist die Oszillatorfrequenzgenauigkeit jedoch wichtig, insbesondere für lange Zeitintervalle oder wenn Sie Messungen auf unterschiedlichen Maschinen vergleichen möchten. Im restlichen Teil dieses Abschnitts werden die Effekte der Oszillatorgenauigkeit untersucht.

Die Schwingungshäufigkeit der Kristalle wird während des Herstellungsprozesses festgelegt und vom Hersteller in Bezug auf eine angegebene Frequenz plus oder minus einer Herstellungstoleranz angegeben, die in "Teile pro Million" (ppm) ausgedrückt wird, der als maximale Frequenzversatz bezeichnet wird. Ein Kristall mit einer angegebenen Frequenz von 1.000.000 Hz und einem maximalen Frequenzoffset von ± 10 ppm wäre innerhalb der Spezifikationsgrenzen, wenn seine tatsächliche Frequenz zwischen 999.990 Hz und 1.000.010 Hz liegt.

Durch das Substituieren der Ausdrucksteile pro Million mit Mikrosekunden pro Sekunde können wir diesen Häufigkeitsversatzfehler auf Zeitintervallmessungen anwenden. Ein Oszillator mit einem Offset von + 10 ppm hätte einen Fehler von 10 Mikrosekunden pro Sekunde. Dementsprechend würde beim Messen eines 1-Sekunden-Intervalls, dieses schnell verlaufen und ein 1-Sekunden-Intervall als 0,999990 Sekunden gemessen werden.

Ein praktischer Verweis ist, dass ein Häufigkeitsfehler von 100 ppm einen Fehler von 8,64 Sekunden nach 24 Stunden verursacht. Diese Tabelle enthält die Messunsicherheit aufgrund des akkumulierten Fehlers für längere Zeitintervalle.

Dauer des Zeitintervalls Messunsicherheit aufgrund akkumulierter Fehler mit +/- 10 PPM-Frequenztoleranz
1 Mikrosekunden ± 10 Picosekunden (10-12)
1 Millisekunden ± 10 Nanosekunden (10-9)
1 Sekunde ± 10 Mikrosekunden
1 Minute ± 60 Mikrosekunden
1 Stunde ± 36 Millisekunden
1 Tag ± 0,86 Sekunden
1 Woche ± 6,08 Sekunden

 

In der vorstehenden Tabelle wird gezeigt, dass bei kleinen Zeitintervallen häufig der Häufigkeitsversatzfehler ignoriert werden kann. Bei langen Zeitintervallen kann sogar ein kleiner Frequenzversatz zu einer erheblichen Messunsicherheit führen.

Kristalloszillatoren, die in Personalcomputern und Servern verwendet werden, werden in der Regel mit einer Frequenztoleranz von ± 30 bis 50 ppm hergestellt, und selten weicht der Kristall um bis zu 500 ppm ab. Obwohl Kristalle mit viel engeren Frequenzversatztoleranzen verfügbar sind, sind sie teurer und werden daher in den meisten Computern nicht verwendet.

Um die nachteiligen Auswirkungen dieses Frequenzversatzfehlers zu verringern, nutzen neuere Versionen von Windows, insbesondere Windows 8, mehrere Hardware-Timer, um den Frequenzversatz zu erkennen und diesen, soweit möglich, zu kompensieren. Dieser Kalibrierungsprozess wird ausgeführt, wenn Windows gestartet wird.

Wie die folgenden Beispiele zeigen, beeinflusst der Frequenzoffsetfehler einer Hardwareuhr die erreichbare Genauigkeit, und die Auflösung der Uhr kann weniger wichtig sein.

Frequenzversatzfehler beeinflusst erreichbare Genauigkeit

Beispiel 1

Angenommen, Sie führen Zeitintervallmessungen mithilfe eines 1 MHz-Oszillators mit einer Auflösung von 1 Mikrosekunden und einem maximalen Frequenzversatzfehler von ±50 ppm durch. Nehmen wir nun an, der Offset beträgt genau +50 ppm. Dies bedeutet, dass die tatsächliche Frequenz 1.000.050 Hz betragen würde. Wenn wir ein Zeitintervall von 24 Stunden gemessen hätten, wäre unsere Messung 4,3 Sekunden zu kurz (23:59:55.700000 gemessen im Vergleich zu 24:00:00.000000 tatsächlich).

Sekunden in einem Tag = 86400

Frequenzoffsetfehler = 50 ppm = 0,00005

86.400 Sekunden * 0,00005 = 4,3 Sekunden

Beispiel 2

Angenommen, der Prozessor-TSC-Takt wird von einem Kristallschwinger gesteuert und hat die angegebene Frequenz von 3 GHz. Dies bedeutet, dass die Auflösung 1/3.000.000.000 oder etwa 333 Picosekunden sein würde. Gehen Sie davon aus, dass der Kristall, der zum Steuern der Prozessoruhr verwendet wird, eine Frequenztoleranz von ±50 ppm aufweist und tatsächlich +50 ppm ist. Trotz der beeindruckenden Auflösung ist eine Zeitintervallmessung von 24 Stunden immer noch 4,3 Sekunden zu kurz. (23:59:55.7000000000 gemessen im Vergleich zu 24:00:00.0000000000 tatsächlich).

Sekunden in einem Tag = 86400

Frequenzoffsetfehler = 50 ppm = 0,00005

86.400 Sekunden * 0,00005 = 4,3 Sekunden

Dies zeigt, dass eine hochauflösende TSC-Uhr nicht notwendigerweise genauere Messungen als eine niedrigere Auflösungsuhr bereitstellt.

Beispiel 3

Erwägen Sie die Verwendung von zwei verschiedenen Computern, um das gleiche 24-Stunden-Zeitintervall zu messen. Beide Computer verfügen über einen Oszillator mit einer maximalen Frequenzversatz von ± 50 ppm. Wie weit auseinander kann die Messung des gleichen Zeitintervalls auf diesen beiden Systemen sein? Wie in den vorherigen Beispielen liefert ± 50 ppm einen maximalen Fehler von ± 4,3 Sekunden nach 24 Stunden. Wenn ein System 4,3 Sekunden schnell ausgeführt wird und die anderen 4,3 Sekunden langsam sind, kann der maximale Fehler nach 24 Stunden 8,6 Sekunden betragen.

Sekunden in einem Tag = 86400

Frequenzoffsetfehler = ±50 ppm = ±0.00005

±(86.400 Sekunden * 0,00005) = ±4,3 Sekunden

Maximaler Offset zwischen den beiden Systemen = 8,6 Sekunden

Zusammenfassend wird der Frequenzversatzfehler immer wichtiger, wenn lange Zeitintervalle gemessen und Messungen zwischen verschiedenen Systemen verglichen werden.

Die Stabilität eines Zeitgebers beschreibt, ob sich die Tickhäufigkeit im Laufe der Zeit ändert, z. B. durch Temperaturänderungen. Quarzkristalle, die als Taktgeneratoren in Computern verwendet werden, zeigen sie kleine Frequenzänderungen abhängig von der Temperatur. Der durch thermische Drift verursachte Fehler ist in der Regel klein im Vergleich zum Frequenzversatzfehler für häufige Temperaturbereiche. Entwickler von Software für tragbare Geräte oder Geräte, die großen Temperaturschwankungen unterliegen, müssen diesen Effekt jedoch möglicherweise berücksichtigen.

Hardwarezeitgeberinformationen

TSC Register (x86 und x64)

Alle modernen Intel- und AMD-Prozessoren enthalten ein TSC-Register, bei dem es sich um ein 64-Bit-Register handelt, das mit einer hohen Rate steigt, normalerweise gleich der Prozessoruhr. Der Wert dieses Zählers kann mit den Maschinenbefehlen RDTSC oder RDTSCP abgerufen werden, was je nach Prozessor sehr geringe Zugriffszeiten und Rechenkosten in der Größenordnung von zehn oder hundert Maschinenzyklen ermöglicht.

Obwohl das TSC-Register wie ein idealer Zeitstempelmechanismus aussieht, sind hier Umstände, in denen es nicht zuverlässig für Zeiterfassungszwecke funktionieren kann:

  • Nicht alle Prozessoren haben verwendbare TSC-Register, so dass die Verwendung des TSC-Registers in Software direkt ein Portabilitätsproblem verursacht. (Windows wählt in diesem Fall eine alternative Zeitquelle für QPC aus, wodurch das Portabilitätsproblem vermieden wird.)
  • Einige Prozessoren können die Häufigkeit der TSC-Uhr variieren oder die Weiterentwicklung des TSC-Registers beenden, wodurch der TSC nicht für Timing-Zwecke auf diesen Prozessoren geeignet ist. Diese Prozessoren sollen nicht invariante TSC-Register besitzen. (Windows erkennt dies automatisch und wählt eine alternative Zeitquelle für QPC aus).
  • Auch wenn ein Virtualisierungshost über einen verwendbaren TSC verfügt, kann die Livemigration ausgeführter virtueller Computer, wenn der Zielvirtualisierungshost keine hardwaregestützte TSC-Skalierung aufweist oder verwendet, zu einer Änderung der TSC-Häufigkeit führen, die für Gäste sichtbar ist. Es wird erwartet, dass, wenn dieser Typ der Live-Migration für einen Gast möglich ist, der Hypervisor das invariante TSC-Featurebit in CPUID löscht.
  • Bei Multiprozessor- oder Multi-Core-Systemen können einige Prozessoren und Systeme die Takte auf jedem Kern nicht mit demselben Wert synchronisieren. (Windows erkennt dies automatisch und wählt eine alternative Zeitquelle für QPC aus).
  • Bei einigen großen Multiprozessorsystemen können Sie die Prozessoruhren möglicherweise nicht mit demselben Wert synchronisieren, auch wenn der Prozessor über einen invarianten TSC verfügt. (Windows erkennt dies automatisch und wählt eine alternative Zeitquelle für QPC aus).
  • Einige Prozessoren führen Anweisungen außerhalb der Reihenfolge aus. Dies kann zu falschen Zyklusanzahlen führen, wenn RDTSC verwendet wird, um Anweisungssequenzen zu zeitieren, da die RDTSC-Anweisung möglicherweise zu einem anderen Zeitpunkt ausgeführt werden kann als in Ihrem Programm angegeben. Die RDTSCP-Anweisung wurde auf einigen Prozessoren als Reaktion auf dieses Problem eingeführt.

Wie bei anderen Timern basiert der TSC auf einem Kristallschwinger, dessen genaue Frequenz im Voraus nicht bekannt ist und einen Frequenzversatzfehler aufweist. Damit sie verwendet werden kann, muss sie mit einer anderen Zeitreferenz kalibriert werden.

Während der Systeminitialisierung prüft Windows, ob der TSC für Zeitplanungszwecke geeignet ist, und führt die erforderliche Frequenzkalibrierung und Kernsynchronisierung durch.

PM Uhr (x86 und x64)

Der ACPI-Timer, auch bekannt als PM-Uhr, wurde der Systemarchitektur hinzugefügt, um zuverlässige Zeitstempel unabhängig von der Prozessorgeschwindigkeit bereitzustellen. Da dies das einzige Ziel dieses Timers war, stellt sie einen Zeitstempel in einem einzelnen Takt bereit, bietet aber keine anderen Funktionen.

HPET Timer (x86 und x64)

Der High Precision Event Timer (HPET) wurde gemeinsam von Intel und Microsoft entwickelt, um die Zeitlichkeitsanforderungen von Multimedia- und anderen zeitempfindlichen Anwendungen zu erfüllen. Im Gegensatz zum TSC, bei dem es sich um eine Prozessorressource handelt, ist der HPET eine gemeinsam genutzte plattformweite Ressource, obwohl ein System mehrere HPETs haben kann. HPET-Unterstützung ist seit Windows Vista verfügbar, und die Hardware-Logo-Zertifizierung für Windows 7 und Windows 8 erfordert HPET-Unterstützung in der Hardwareplattform.

Generischer Timer-Systemzähler (Arm)

Arm-basierte Plattformen verfügen nicht über eine TSC-, HPET- oder PM-Uhr, wie es auf Intel- oder AMD-basierten Plattformen gibt. Stattdessen stellen Arm-Prozessoren den generischen Timer (manchmal als generischer Intervalltimer oder GIT bezeichnet) bereit, der ein Systemzählerregister (z. B. CNTVCT_EL0) enthält. Der generische Timer-Systemzähler ist eine plattformweite Zeitquelle mit fester Frequenz. Sie beginnt bei der Inbetriebnahme bei Null und steigt mit hoher Rate. In Armv8.6 oder höher wird dies als genau 1 GHz definiert, sollte jedoch durch das Lesen des Taktfrequenzregisters bestimmt werden, das durch frühe Start-Firmware festgelegt wird. Weitere Informationen finden Sie im Kapitel "Der generische Timer im AArch64-Zustand" im "Arm Architektur-Referenzhandbuch für A-Profil-Architektur" (DDI 0487).

Zykluszähler (Arm)

Arm-basierte Plattformen bieten ein Leistungsmonitor-Zykluszählerregister (z. B. PMCCNTR_EL0). Dieser Zähler zählt Prozessoruhrzyklen. Es ist nicht invariant und seine Einheiten können nicht mit Echtzeit korreliert werden. Es wird nicht empfohlen, dieses Register zum Abrufen von Zeitstempeln zu verwenden.