Niedawno zdecydowałem, że muszę zmienić użycie milisekund na mikrosekundy dla mojej klasy Timer, a po kilku badaniach zdecydowałem, że QueryPerformanceCounter jest prawdopodobnie moim najbezpieczniejszym zakładem. (Ostrzeżenie Boost::Posix
, że może nie działać na Win32 API, trochę mnie zraziło). Jednak nie jestem pewien, jak to zaimplementować.
To, co robię, to wywołanie dowolnej GetTicks()
funkcji esque, której używam i przypisanie jej do startingTicks
zmiennej Timera . Następnie, aby znaleźć ilość czasu, który upłynął, po prostu odejmuję wartość zwracaną przez funkcję od wartości startingTicks
, a kiedy resetuję licznik czasu, po prostu wywołuję funkcję ponownie i przypisuję do niej startTicks. Niestety, z kodu, który widziałem, nie jest tak proste, jak samo wywołanie QueryPerformanceCounter()
i nie jestem pewien, co mam podać jako jego argument.
Odpowiedzi:
Ten program powinien wypisać liczbę bliską 1000 (stan uśpienia systemu Windows nie jest tak dokładny, ale powinien wynosić 999).
StartCounter()
Funkcja rejestruje liczbę kleszczy licznik wydajność ma wCounterStart
zmiennej.GetCounter()
Funkcja zwraca liczbę milisekund odStartCounter()
ostatnio zwanych jako podwójne, więc jeśliGetCounter()
powróci 0.001 następnie został on około 1 mikrosekundy ponieważStartCounter()
został powołany.Jeśli chcesz mieć timer, użyj zamiast tego sekund, a następnie zmień
do
lub jeśli chcesz mikrosekund, użyj
Ale tak naprawdę chodzi o wygodę, ponieważ zwraca podwójną.
źródło
On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL).
Ten kod nie jest bardzo wadliwy, ale trochę BIOS lub HAL.StartCounter
:old_mask = SetThreadAffinityMask(GetCurrentThread,1);
a następnie ustawiłem z powrotem na końcuSetThreadAffinityMask ( GetCurrentThread , old_mask ) ;
. Mam nadzieję, że to wystarczy. Powinno to zapobiec zmianie harmonogramu mojego wątku na cokolwiek innego niż pierwszy rdzeń procesora. (Co jest oczywiście tylko rozwiązaniem dla środowiska testowego)Używam tych definicji:
Użycie (nawiasy, aby zapobiec przedefiniowaniu):
Dane wyjściowe z przykładu użycia:
źródło
Zakładając, że korzystasz z systemu Windows (jeśli tak, powinieneś oznaczyć swoje pytanie jako takie!), Na tej stronie MSDN możesz znaleźć źródło prostej, użytecznej
HRTimer
klasy C ++, która opakowuje potrzebne wywołania systemowe, aby zrobić coś bardzo zbliżonego do tego, czego potrzebujesz (byłoby łatwo dodaćGetTicks()
do niego metodę, w szczególności zrobić dokładnie to, czego potrzebujesz).Na platformach innych niż Windows nie ma funkcji QueryPerformanceCounter, więc rozwiązanie nie będzie bezpośrednio przenośne. Jeśli jednak umieścisz go w klasie takiej jak wspomniana powyżej
HRTimer
, łatwiej będzie zmienić implementację klasy, aby korzystać z tego, co aktualnie platforma jest w stanie zaoferować (może przez Boost lub cokolwiek!).źródło
Rozszerzyłbym to pytanie o przykład sterownika NDIS dotyczący uzyskiwania czasu. Jak wiadomo, KeQuerySystemTime (naśladowany w NdisGetCurrentSystemTime) ma niską rozdzielczość powyżej milisekund, a niektóre procesy, takie jak pakiety sieciowe lub inne IRP, mogą wymagać lepszego znacznika czasu;
Przykład jest równie prosty:
gdzie dzielnik to 10 ^ 3 lub 10 ^ 6 w zależności od wymaganej rozdzielczości.
źródło