Zmierz czas w Linuksie-time vs clock vs getrusage vs clock gettime vs gettimeofday vs timespec get?

Wśród funkcji czasu, time, clock getrusage, clock_gettime, gettimeofday i timespec_get, chcę jasno zrozumieć, w jaki sposób są one wdrażane i jakie są ich wartości zwrotne, aby wiedzieć, w jakiej sytuacji muszę z nich korzystać.

Najpierw musimy sklasyfikować funkcje zwracające wartości zegara ściennego porównaj z funkcjami zwracającymi wartości procesu lub wątków. gettimeofday Zwraca wartość zegara ściennego, clock_gettime Zwraca wartość zegara ściennego lub wartości procesu lub wątków w zależności na przekazanym do niego parametrze Clock. getrusage i clock zwracają wartości procesu.

Drugie pytanie dotyczy implementacji tych funkcji, a w konsekwencji ich dokładności. Z jakiego mechanizmu sprzętowego lub programowego korzystają te funkcje.

Wydaje się, że getrusage używa tylko Kernel tick (Zwykle o długości 1ms) i w konsekwencji nie może być dokładniejszy niż ms. Czy to prawda? Wtedy funkcja getimeofday wydaje się używać najdokładniejszego dostępnego sprzętu bazowego. W konsekwencji jego dokładność jest zwykle mikrosekundy (nie może być większa ze względu na API) na najnowszym sprzęcie. Co z clock, strona podręcznika mówi o "przybliżeniu", co to znaczy? A co z clock_gettime, API jest w nanosekundzie, czy to znaczy, że jest w stanie być tak dokładne, jeśli pozwala na to podstawowy sprzęt? A co z monotonicznością?

Czy są jakieś inne funkcje?

2 answers

Problem polega na tym, że istnieje kilka różnych funkcji czasu dostępnych w C i C++, a niektóre z nich różnią się zachowaniem między implementacjami. Istnieje również wiele pół-odpowiedzi pływających wokół. Skompilowanie listy funkcji zegara wraz z ich właściwościami odpowiedziałoby poprawnie na pytanie. Na początek zapytajmy, jakie są odpowiednie właściwości, których szukamy. Patrząc na twój post, proponuję:

  • jaki czas jest mierzony przez zegar? (real, user, system, Czy, mam nadzieję, Nie, zegar ścienny?)
  • Jaka jest precyzja zegara? (s, ms, µs, czy szybciej?)
  • Po jakim czasie zegar owija się wokół? A może istnieje jakiś mechanizm, aby tego uniknąć?
  • jest monotoniczny zegar, czy zmieni się wraz ze zmianami w czasie systemowym (poprzez NTP, strefę czasową, czas letni, przez użytkownika itp.)?
  • czym różnią się powyższe implementacje?
  • jest określoną funkcją przestarzałą, niestandardową, itd.?

Przed rozpoczęciem listy, chciałbym zwrócić uwagę, że zegar ścienny rzadko jest właściwym czasem do wykorzystania, podczas gdy zmienia się wraz ze zmianami strefy czasowej, zmianami czasu letniego lub jeśli zegar ścienny jest synchronizowany przez NTP. Żadna z tych rzeczy nie jest dobra, jeśli wykorzystujesz czas na planowanie wydarzeń lub porównywanie wydajności. To jest naprawdę dobre tylko dla tego, co mówi nazwa, zegar na ścianie (lub pulpit).

Oto co znalazłem do tej pory na zegary w Linuksie i OS X:

  • time() zwraca zegar ścienny z systemu operacyjnego, z precyzją w sekundach.
  • clock() wydaje się zwracać sumę czasu użytkownika i systemu. Występuje w wersji C89 i późniejszych. Kiedyś miał to być czas procesora w cyklach, ale nowoczesne standardy , takie jak POSIX wymagają, aby CLOCKS_PER_SEC wynosił 1000000, co daje maksymalną możliwą dokładność 1 µs. Precyzja w moim systemie to rzeczywiście 1 µs. Ten zegar owija się, gdy tylko się skończy (zwykle dzieje się tak po ~2^32 kleszczach, co nie jest zbyt długie jak na zegar 1 MHz). man clock mówi, że od glibc 2.18 jest on zaimplementowany z clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) w Linuksie.
  • clock_gettime(CLOCK_MONOTONIC, ...) zapewnia rozdzielczość nanosekund, jest monotoniczna. Wierzę ,że "sekundy" i "nanosekundy" są przechowywane osobno, każda w licznikach 32-bitowych. Tak więc każde owinięcie nastąpi po kilkudziesięciu latach bezawaryjnej pracy. Wygląda to na bardzo dobry zegar, ale niestety nie jest jeszcze dostępny na OS X. POSIX 7 opisuje CLOCK_MONOTONIC jako opcjonalne rozszerzenie .
  • getrusage() okazał się najlepszym wyborem dla mojej sytuacji. Raportuje czasy użytkownika i systemu oddzielnie i nie owija się. Precyzja w moim systemie wynosi 1 µs, ale testowałem ją również na systemie Linux (Red Hat 4.1.2-48 z GCC 4.1.2) i tam precyzja wynosiła tylko 1 ms.
  • gettimeofday() zwraca czas zegara ściennego z (nominalnie) dokładnością µs. W moim systemie ten zegar wydaje się mieć µs precyzja, ale nie jest to gwarantowane, ponieważ "rozdzielczość zegara systemowego jest zależna od sprzętu" . POSIX.1-2008 mówi, że . "Aplikacje powinny używać funkcji clock_gettime() zamiast przestarzałej funkcji gettimeofday()", więc powinieneś trzymać się od niej z daleka. Linux x86 i implementuje go jako wywołanie systemowe .
  • mach_absolute_time() jest to opcja dla bardzo wysokiej rozdzielczości (ns) czas na OS X. W moim systemie, to rzeczywiście daje rozdzielczość ns. W zasadzie to zegar owija się, jednak przechowuje ns używając 64-bitowej niepodpisanej liczby całkowitej, więc owijanie nie powinno być problemem w praktyce. Przenośność jest wątpliwa.
  • napisałem hybrydową funkcję na podstawie tego fragmentu , który używa clock_gettime podczas kompilacji na Linuksie, lub mach timer podczas kompilacji na OS X, aby uzyskać precyzję ns zarówno na Linuksie, jak i OS X. {17]}

Wszystkie powyższe istnieją zarówno w Linuksie, jak i OS X, o ile nie określono inaczej. "Moje system " w powyższym jest Apple z systemem OS X 10.8.3 z GCC 4.7.2 od MacPorts.

Na koniec, oto lista referencji, które znalazłem pomocne w uzupełnieniu do linków powyżej:


Update : dla OS X, {[11] } został zaimplementowany od 10.12 (Sierra). Ponadto, zarówno platformy oparte na POSIX, jak i BSD (takie jak OS X) współdzielą pole struct rusage.ru_utime.

 166
Author: Douglas B. Staple,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:09

C11 timespec_get

Przykład użycia w: https://stackoverflow.com/a/36095407/895245

Maksymalna możliwa precyzja zwracana jest nanosekundami, ale rzeczywista precyzja jest zdefiniowana i może być mniejsza.

Zwraca czas ściany, nie użycie procesora.

Glibc 2.21 implementuje go Pod sysdeps/posix/timespec_get.c i przekazuje bezpośrednio do:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettime oraz CLOCK_REALTIME są POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html i man clock_gettime mówi, że ta miara może mieć nieciągłości, jeśli zmienisz jakieś ustawienie czasu systemowego podczas uruchamiania programu.

C++11 chrono

Skoro już o tym mowa, zajrzyjmy też do nich: http://en.cppreference.com/w/cpp/chrono

[17]} GCC 5.3.0 (C++ stdlib jest wewnątrz GCC source):
  • high_resolution_clock jest aliasem dla system_clock
  • system_clock do przodu do pierwszego z poniższych, które są dostępne:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock do przodu do pierwszego z poniższych, które są dostępne:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

Zapytany o: różnica między std::system_clock i std::steady_clock?

CLOCK_REALTIME vs CLOCK_MONOTONIC: różnica między CLOCK_REALTIME i CLOCK_MONOTONIC?

 13
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-06 10:05:11