Problém je v tom, že v C a C++ je k dispozici několik různých časových funkcí a některé z nich se liší v chování mezi implementacemi. Kolem je také spousta polovičních odpovědí. Sestavení seznamu hodinových funkcí spolu s jejich vlastnostmi by správně odpovědělo na otázku. Pro začátek se zeptejme, jaké jsou relevantní vlastnosti, které hledáme. Při pohledu na váš příspěvek navrhuji:
- Jaký čas měří hodiny? (skutečné, uživatelské, systémové nebo, doufejme, že ne, nástěnné hodiny?)
- Jaká je přesnost hodin? (s, ms, µs nebo rychlejší?)
- Po jaké době se hodiny obtáčí? Nebo existuje nějaký mechanismus, jak se tomu vyhnout?
- Jsou hodiny monotónní, nebo se budou měnit se změnami systémového času (prostřednictvím NTP, časového pásma, letního času, uživatelem atd.)?
- Jak se výše uvedené liší mezi implementacemi?
- Je konkrétní funkce zastaralá, nestandardní atd.?
Než začnu seznam, rád bych zdůraznil, že čas nástěnných hodin je zřídka tím správným časem k použití, zatímco se mění se změnami časového pásma, změnou letního času nebo pokud jsou nástěnné hodiny synchronizovány pomocí NTP. Žádná z těchto věcí není dobrá, pokud čas využíváte k plánování událostí nebo ke srovnávání výkonu. Je to opravdu dobré pouze pro to, co říká název, hodiny na stěně (nebo na ploše).
Zde je to, co jsem zatím našel pro hodiny v Linuxu a OS X:
time()
vrátí čas nástěnných hodin z operačního systému s přesností v sekundách.clock()
Zdá se, že vrací součet času uživatele a systému. Je přítomen v C89 a novějších. Kdysi to měl být čas CPU v cyklech, ale moderní standardy jako POSIX vyžadují, aby CLOCKS_PER_SEC bylo 1000000, což dává maximální možnou přesnost 1 µs. Přesnost na mém systému je skutečně 1 µs. Tyto hodiny se zalomí, jakmile se vyčerpají (k tomu obvykle dochází po ~2^32 tikáních, což není příliš dlouho pro hodiny 1 MHz).man clock
říká, že od glibc 2.18 je implementován sclock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)
v Linuxu.clock_gettime(CLOCK_MONOTONIC, ...)
poskytuje nanosekundové rozlišení, je monotónní. Věřím, že „sekundy“ a „nanosekundy“ jsou uloženy odděleně, každá v 32bitových čítačích. K jakémukoli zalomení by tedy došlo po mnoha desítkách let provozuschopnosti. Vypadá to jako velmi dobré hodiny, ale bohužel ještě nejsou dostupné na OS X. POSIX 7 popisujeCLOCK_MONOTONIC
jako volitelné rozšíření.getrusage()
se pro mou situaci ukázalo jako nejlepší volba. Hlásí uživatelské a systémové časy odděleně a nezalamuje se. Přesnost na mém systému je 1 µs, ale testoval jsem to také na systému Linux (Red Hat 4.1.2-48 s GCC 4.1.2) a tam byla přesnost pouze 1 ms.gettimeofday()
vrátí čas nástěnných hodin s (nominálně) µs přesností. Na mém systému se zdá, že tyto hodiny mají přesnost µs, ale není to zaručeno, protože "rozlišení systémových hodin je závislé na hardwaru". POSIX.1-2008 to říká. "Aplikace by měly používatclock_gettime()
místo zastaralé funkcegettimeofday()
funkce", takže byste se od ní měli držet dál. Linux x86 a implementuje ji jako systémové volání.mach_absolute_time()
je volba pro velmi vysoké rozlišení (ns) časování v OS X. V mém systému to skutečně dává rozlišení ns. V principu se tyto hodiny obtáčí, nicméně ukládají ns pomocí 64bitového celého čísla bez znaménka, takže s obtékáním by v praxi neměl být problém. Přenositelnost je sporná.- Napsal jsem hybridní funkci založenou na tomto úryvku, která používá clock_gettime při kompilaci v Linuxu nebo Mach timer při kompilaci v OS X, abych dosáhla přesnosti ns v Linuxu i OS X.
Všechny výše uvedené existují v Linuxu i OS X, pokud není uvedeno jinak. "Můj systém" ve výše uvedeném je Apple se systémem OS X 10.8.3 s GCC 4.7.2 z MacPorts.
Nakonec zde je seznam odkazů, které mi kromě výše uvedených odkazů pomohly:
- http://blog.habets.pp.se/2010/09/gettimeofday-should-never-be-used-to-measure-time
- Jak změřit SKUTEČNOU dobu provádění programu C pod Linuxem?
- http://digitalsandwich.com/archives/27-benchmarking-misconceptions-microtime-vs-getrusage.html
- http://www.unix.com/hp-ux/38937-getrusage.html
Aktualizovat :pro OS X, clock_gettime
byla implementována od 10.12 (Sierra). Také platformy založené na POSIX a BSD (jako OS X) sdílejí rusage.ru_utime
struct pole.
C11 timespec_get
Příklad použití na:https://stackoverflow.com/a/36095407/895245
Maximální možná vrácená přesnost je nanosekundy, ale skutečná přesnost je definována implementací a mohla by být menší.
Vrací čas zdi, nikoli využití CPU.
glibc 2.21 jej implementuje pod sysdeps/posix/timespec_get.c
a přeposílá přímo na:
clock_gettime (CLOCK_REALTIME, ts) < 0)
clock_gettime
a CLOCK_REALTIME
jsou POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html a man clock_gettime
říká, že toto opatření může mít nespojitosti, pokud změníte některé nastavení systémového času během běhu programu.
C++ 11 chrono
Když už jsme u toho, pojďme se jim věnovat také:http://en.cppreference.com/w/cpp/chrono
GCC 5.3.0 (C++ stdlib je ve zdroji GCC):
high_resolution_clock
je alias prosystem_clock
system_clock
přesměruje na první z následujících dostupných:clock_gettime(CLOCK_REALTIME, ...)
gettimeofday
time
steady_clock
přesměruje na první z následujících dostupných:clock_gettime(CLOCK_MONOTONIC, ...)
system_clock
Dotaz na:Rozdíl mezi std::system_clock a std::steady_clock?
CLOCK_REALTIME
vs CLOCK_MONOTONIC
:Rozdíl mezi CLOCK_REALTIME a CLOCK_MONOTONIC?