In Win32 gibt es eine Möglichkeit, eine eindeutige CPU-Zykluszahl oder Ähnliches zu erhalten, die für mehrere Prozesse / Sprachen / Systeme / etc. einheitlich ist.
Ich erstelle einige Protokolldateien, muss aber mehrere Protokolldateien erstellen, weil wir die .NET-Laufzeitumgebung hosten, und ich möchte es vermeiden, von einem zum anderen Protokoll aufzurufen. Daher dachte ich, ich würde einfach zwei Dateien erzeugen, sie kombinieren und sie dann sortieren, um eine kohärente Zeitleiste zu erhalten, die weltübergreifende Anrufe beinhaltet.
GetTickCount erhöht sich jedoch nicht bei jedem Anruf, daher ist das nicht zuverlässig. Gibt es eine bessere Nummer, damit ich beim Sortieren die Anrufe in der richtigen Reihenfolge bekomme?
Bearbeiten : Dank @Greg habe ich mich auf den Weg zu QueryPerformanceCounter gemacht , die den Trick gemacht haben.
Sie können die RDTSC CPU-Anweisung verwenden (vorausgesetzt, x86). Diese Anweisung gibt den CPU-Zyklus-Zähler, aber beachten Sie, dass es sehr schnell auf seinen maximalen Wert erhöht und dann auf 0 zurückgesetzt wird. Wie der Wikipedia-Artikel erwähnt, ist es besser, die QueryPerformanceCounter Funktion.
Hier ist ein interessanter Artikel! sagt, dass Sie nicht RDTSC verwenden sollen, sondern stattdessen QueryPerformanceCounter .
Fazit:
Benutze reguläres altes
timeGetTime()
zu tun Timing ist bei vielen nicht zuverlässig Windows-basierte Betriebssysteme weil die Granularität des Systems Timer kann so hoch wie 10-15 sein Millisekunden, das bedeutettimeGetTime()
ist nur korrekt 10-15 Millisekunden. [Notiere dass der hohe Granularitäten treten auf NT-Basis auf Betriebssysteme wie Windows NT, 2000 und XP. Windows 95 und 98 neigen dazu um eine viel bessere Granularität zu haben, etwa 1-5 ms.]Allerdings, wenn Sie anrufen
timeBeginPeriod(1)
am Anfang von Ihr Programm (undtimeEndPeriod(1)
at das Ende),timeGetTime()
wird normalerweise werden auf 1-2 Millisekunden genau, und wird dich extrem versorgen genaue Timing-Informationen.
Sleep()
verhält sich ähnlich; die Länge von Zeit, dieSleep()
tatsächlich schläft denn geht Hand in Hand mit dem Granularität vontimeGetTime()
, also nach rufttimeBeginPeriod(1)
einmal auf,Sleep(1)
wird tatsächlich für 1-2 schlafen Millisekunden,Sleep(2)
für 2-3 und so auf (anstatt in Schritten zu schlafen so hoch wie 10-15 ms).Für ein präziseres Timing (Genauigkeit im Millisekundenbereich), werden Sie wahrscheinlich vermeiden wollen, die Assembly Mnemonic RDTSC, weil es ist schwer zu kalibrieren ; stattdessen verwenden
QueryPerformanceFrequency
undQueryPerformanceCounter
, das sind genau auf weniger als 10 Mikrosekunden (0,00001 Sekunden).Für einfaches Timing, sowohl timeGetTime und QueryPerformanceCounter funktionieren gut, und QueryPerformanceCounter ist offensichtlich genauer. Wie auch immer, wenn Sie müssen jede Art von "zeitlich abgestimmt" tun Pausen "(wie die für Bildfrequenzbegrenzung), müssen Sie sein vorsichtig, in einer Schleife zu sitzen, die ruft QueryPerformanceCounter, wartet auf um einen bestimmten Wert zu erreichen; dieser Wille verschlinge 100% deines Prozessors. Betrachten Sie stattdessen ein hybrides Schema, wo du Schlaf nennst (1) (vergiss nicht timeBeginPeriod (1) zuerst!) wann immer Sie müssen mehr als 1 ms von übergeben werden Zeit, und geben Sie dann nur die QueryPerformanceCounter 100% -Busy-Schleife um das letzte & lt; 1/1000 eines Sekunde der Verzögerung, die Sie brauchen. Dies gibt Ihnen ultra-genaue Verzögerungen (genau bis 10 Mikrosekunden), mit sehr geringe CPU-Auslastung. Siehe den Code oben.
System.Diagnostics.Stopwatch.GetTimestamp () gibt die Anzahl der CPU-Zyklus seit einem Zeitpunkt der Herkunft (vielleicht, wenn der Computer gestartet, aber ich bin mir nicht sicher) und ich habe noch nie gesehen, es nicht zwischen 2 Anrufe erhöht.
Die CPU-Zyklen sind für jeden Computer spezifisch, so dass Sie die Protokolldatei nicht zwischen zwei Computern zusammenführen können.
Die RDTSC-Ausgabe kann von der Taktfrequenz des aktuellen Kerns abhängen, die für moderne CPUs weder konstant noch in einer Mehrkernmaschine konsistent ist.
Verwenden Sie die Systemzeit, und wenn Sie Feeds von mehreren Systemen verwenden, verwenden Sie eine NTP-Zeitquelle. Sie können auf diese Weise zuverlässige, konsistente Zeitwerte erhalten; Wenn der Overhead für Ihre Zwecke zu hoch ist, verwenden Sie HPET , um die Zeit zu berechnen, die seit der letzten bekannten zuverlässigen Zeitmessung verstrichen ist besser als die HPET allein.
Verwenden Sie GetTickCount und fügen Sie beim Zusammenführen der Protokolldateien einen weiteren Zähler hinzu. Gibt Ihnen keine perfekte Reihenfolge zwischen den verschiedenen Protokolldateien, aber es wird mindestens alle Protokolle aus jeder Datei in der richtigen Reihenfolge behalten.
Tags und Links timer winapi cpu-cycles