Die Bibliothek Boost.Chrono bietet verschiedene Uhren an. So können Sie zum Beispiel die aktuelle Uhrzeit erhalten, so wie sie üblicherweise auf dem Desktop Ihres Computers angezeigt wird. Sie können jedoch auch Uhren verwenden, die es Ihnen erlauben zu messen, wie viel Zeit in einem Prozess verstrichen ist.
Boost.Chrono ist teilweise in den Standard C++11 eingegangen. So können Sie, wenn Ihre Entwicklungsumgebung C++11 unterstützt, auf einige Uhren über die Headerdatei chrono
zugreifen. C++11 bietet aber zum Beispiel keine Uhren an, um die CPU-Zeit zu messen. Boost.Chrono unterstützt außerdem eine benutzerdefinierte Formatierung zur Ausgabe von Zeiten.
Sie können auf alle Uhren aus Boost.Chrono über die Headerdatei boost/chrono.hpp
zugreifen. Einzige Ausnahme ist die benutzerdefinierte Formatierung. In diesem Fall müssen Sie zusätzlich die Headerdatei boost/chrono_io.hpp
einbinden.
#include <boost/chrono.hpp>
#include <iostream>
using namespace boost::chrono;
int main()
{
std::cout << system_clock::now() << '\n';
#ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
std::cout << steady_clock::now() << '\n';
#endif
std::cout << high_resolution_clock::now() << '\n';
#ifdef BOOST_CHRONO_HAS_PROCESS_CLOCKS
std::cout << process_real_cpu_clock::now() << '\n';
std::cout << process_user_cpu_clock::now() << '\n';
std::cout << process_system_cpu_clock::now() << '\n';
std::cout << process_cpu_clock::now() << '\n';
#endif
#ifdef BOOST_CHRONO_HAS_THREAD_CLOCK
std::cout << thread_clock::now() << '\n';
#endif
}
Beispiel 37.1 stellt alle Uhren vor, die Boost.Chrono anbietet. Allen Uhren ist gemeinsam, dass sie eine Methode now()
definieren, die einen Zeitpunkt zurückgibt. Alle Zeitpunkte werden abhängig von der Uhr relativ zu einem universell gültigen Zeitpunkt gemessen. Man spricht dabei von einer Epoche. Eine oft verwendete Epoche ist der 1. Januar 1970. Wenn Sie Beispiel 37.1 ausführen, wird für alle Zeitpunkte die Epoche mit ausgegeben.
Boost.Chrono kennt folgende Uhren:
boost::chrono::system_clock
gibt die Systemzeit an. Das ist die Uhrzeit, wie sie auf einem Computer angezeigt wird. Ändern Sie die Uhrzeit auf Ihrem Computer, gibt boost::chrono::system_clock
die neue Uhrzeit an. Wenn Sie Beispiel 37.1 ausführen, wird beispielsweise 13919594042183544 [1/10000000]seconds since Jan 1, 1970
ausgegeben.
Die Epoche ist für boost::chrono::system_clock
nicht standardisiert. Dass es sich wie an der Ausgabe zu erkennen um den 1. Januar 1970 handelt, ist ein Detail der aktuellen Implementation. Möchten Sie unabhängig von der Implementation die Zeit seit 1. Januar 1970 erhalten, verwenden Sie die Methode to_time_t()
. Es handelt sich dabei um eine statische Methode, der Sie die aktuelle Systemzeit übergeben und die die Anzahl der Sekunden seit 1. Januar 1970 als std::time_t
zurückgibt.
Bei boost::chrono::steady_clock
handelt es sich um eine Uhr, die garantiert, dass sie bei einem Zugriff zu einem späteren Zeitpunkt auch eine spätere Uhrzeit zurückgibt. Auch dann, wenn die Uhrzeit auf einem Computer zurückgestellt wird, gibt boost::chrono::steady_clock
eine spätere Zeit zurück. Auf Englisch wird diese Zeit monotonic time genannt.
Beispiel 37.1 gibt zum Beispiel 10594369282958 nanoseconds since boot
aus. Die Zeit wird abhängig vom letztmaligen Bootvorgang gemessen. Dabei handelt es sich ebenfalls um ein Detail der Implementation, das sich jederzeit ändern kann.
boost::chrono::steady_clock
kann nicht auf allen Plattformen angeboten werden. Nur wenn das Makro BOOST_CHRONO_HAS_CLOCK_STEADY
definiert ist, steht diese Uhr zur Verfügung.
boost::chrono::high_resolution_clock
ist eine Typdefinition für boost::chrono::system_clock
oder boost::chrono::steady_clock
– je nachdem, welche dieser beiden Uhren Zeit präziser misst. Die Ausgabe ist demnach identisch zu der Uhr, die boost::chrono::high_resolution_clock
hinterlegt ist.
boost::chrono::process_real_cpu_clock
gibt die Zeit an, die ein Programm läuft. Es wird die Zeit seit dem Programmstart gemessen. Wenn Sie Beispiel 37.1 ausführen, wird zum Beispiel 1000000 nanoseconds since process start-up
auf die Standardausgabe ausgegeben.
Sie können anstatt mit boost::chrono::process_real_cpu_clock
auch mit std::clock()
aus ctime
die Zeit erhalten, die ein Programm läuft. Die aktuelle Implementation von boost::chrono::process_real_cpu_clock
basiert auf std::clock()
.
Beachten Sie, dass Sie boost::chrono::process_real_cpu_clock
sowie andere Uhren für die CPU-Zeit nur verwenden können, wenn das Makro BOOST_CHRONO_HAS_PROCESS_CLOCKS
definiert ist.
boost::chrono::process_user_cpu_clock
gibt die Zeit an, die ein Programm im User Space läuft. Der User Space bezieht sich dabei auf Code eines Programms, der unabhängig vom Betriebssystem läuft. Die Zeit, die benötigt wird, um Code von Betriebssystemfunktionen auszuführen, die in einem Programm aufgerufen werden, wird nicht miteinberechnet.
boost::chrono::process_user_cpu_clock
gibt ausschließlich die Zeit an, in der Programmcode im User Space ausgeführt wird. Wird ein Programm zum Beispiel mit einer Funktion wie Sleep()
, wie sie unter Windows zur Verfügung steht, für einige Zeit angehalten, wird diese Zeit von boost::chrono::process_user_cpu_clock
nicht miteinberechnet, da während des Aufrufs von Sleep()
kein Programmcode im User Space ausgeführt wird.
Beispiel 37.1 gibt zum Beispiel 15600100 nanoseconds since process start-up
aus.
boost::chrono::process_system_cpu_clock
ist vergleichbar mit boost::chrono::process_user_cpu_clock
. Es wird jedoch nicht die Zeit gemessen, die ein Programm im User Space läuft, sondern die es im Kernel Space verbringt. boost::chrono::process_system_cpu_clock
gibt die Zeit an, die für die Ausführung von Betriebssystemfunktionen, die in einem Programm aufgerufen werden, verstrichen ist.
Beispiel 37.1 kann zum Beispiel 0 nanoseconds since process start-up
ausgeben. Da das Beispielprogramm keine Betriebssystemfunktionen direkt aufruft und auch in Boost.Chrono nur wenige Betriebssystemfunktionen verwendet werden, wird so wenig Code im Kernel Space ausgeführt, dass boost::chrono::process_system_cpu_clock
0 zurückgeben kann.
boost::chrono::process_cpu_clock
gibt ein Tupel zurück, das die Zeiten enthält, die jeweils einzeln mit boost::chrono::process_real_cpu_clock
, boost::chrono::process_user_cpu_clock
und boost::chrono::process_system_cpu_clock
ermittelt werden können. Beispiel 37.1 gibt beispielsweise {1000000;15600100;0} nanoseconds since process start-up
aus.
boost::chrono::thread_clock
gibt die Zeit an, in der Code in einem Thread ausgeführt wurde. Die von boost::chrono::thread_clock
gemessene Zeit ist vergleichbar mit der CPU-Zeit, nur dass sie nicht für ein Programm, sondern für einen Thread gilt. Außerdem wird nicht zwischen User und Kernel Space unterschieden.
boost::chrono::thread_clock
kann nicht auf allen Plattformen zur Verfügung gestellt werden. Diese Uhr kann nur verwendet werden, wenn das Makro BOOST_CHRONO_HAS_THREAD_CLOCK
definiert ist.
Boost.Chrono stellt ein weiteres Makro BOOST_CHRONO_THREAD_CLOCK_IS_STEADY
zur Verfügung, um herauszufinden, ob boost::chrono::thread_clock
so wie boost::chrono::steady_clock
monotonic time misst.
Wenn Sie Beispiel 37.1 ausführen, wird zum Beispiel 15600100 nanoseconds since thread start-up
ausgegeben.
Beachten Sie, dass alle von Boost.Chrono angebotenen Uhren auf Betriebssystemfunktionen angewiesen sind. Es hängt demnach vom Betriebssystem ab, wie genau und verlässlich die zurückgegebenen Zeiten sind.
#include <boost/chrono.hpp>
#include <iostream>
using namespace boost::chrono;
int main()
{
process_real_cpu_clock::time_point p = process_real_cpu_clock::now();
std::cout << p << '\n';
std::cout << p - nanoseconds{1} << '\n';
std::cout << p + milliseconds{1} << '\n';
std::cout << p + seconds{1} << '\n';
std::cout << p + minutes{1} << '\n';
std::cout << p + hours{1} << '\n';
}
Der Aufruf von now()
gibt für alle Uhren ein Objekt vom Typ boost::chrono::time_point
zurück. boost::chrono::time_point
ist eng mit einer Uhr verzahnt, da ein Zeitpunkt nur abhängig von einem absoluten Referenzpunkt gemessen werden kann – und dieser ist in Boost.Chrono per Uhr definiert. boost::chrono::time_point
ist entsprechend ein Template, das unter anderem eine Uhrenklasse als Parameter erwartet. Uhrenklassen bietet ihrerseits eine Typedefinition für ihren spezialisierten boost::chrono::time_point
an. process_real_cpu_clock::time_point
ist die entsprechende Typdefinition für die Uhrenklasse process_real_cpu_clock
.
Neben boost::chrono::time_point
bietet Boost.Chrono eine Klasse boost::chrono::duration
an, die Zeiträume beschreibt. Da es sich bei boost::chrono::duration
ebenfalls um ein Template handelt, bietet Boost.Chrono mit boost::chrono::nanoseconds
, boost::chrono::milliseconds
, boost::chrono::microseconds
, boost::chrono::seconds
, boost::chrono::minutes
und boost::chrono::hours
sechs einfach zu verwendende Klassen an.
Boost.Chrono überlädt viele Operatoren, um mit Zeitpunkten und -räumen arbeiten zu können. So werden im Beispiel 37.2 Zeiträume von p subtrahiert oder zu p hinzuaddiert, um neue Zeitpunkte zu erhalten. Diese werden direkt auf die Standardausgabe ausgegeben.
Wenn Sie Beispiel 37.2 ausführen, stellen Sie fest, dass die Ausgabe aller Zeitpunkte mit der Einheit Nanosekunden erfolgt. Beim Arbeiten mit Zeitpunkten und -räumen verwendet Boost.Chrono automatisch die kleinste Einheit, um sicherzustellen, dass Ergebnisse exakt sind. Möchten Sie einen Zeitpunkt mit einer anderen Einheit verwenden, müssen Sie ihn casten.
boost::chrono::time_point_cast()
#include <boost/chrono.hpp>
#include <iostream>
using namespace boost::chrono;
int main()
{
process_real_cpu_clock::time_point p = process_real_cpu_clock::now();
std::cout << p << '\n';
std::cout << time_point_cast<minutes>(p) << '\n';
}
Boost.Chrono stellt mit boost::chrono::time_point_cast()
eine Funktion zur Verfügung, die wie ein Cast-Operator verwendet wird. So können Sie wie im Beispiel 37.3 einen Zeitpunkt, der auf der Einheit Nanosekunden basiert, in einen Zeitpunkt umwandeln, der auf Minuten basiert. Da nicht jeder beliebige Zeitpunkt in Nanosekunden gemessen als Zeitpunkt in Minuten dargestellt werden kann, muss boost::chrono::time_point_cast()
verwendet werden. Die entgegengesetzte Umwandlung von Minuten in Nanosekunden ist implizit möglich – Sie müssen in diesem Fall nicht auf boost::chrono::time_point_cast()
zugreifen.
Boost.Chrono stellt auch für Zeiträume einen Cast-Operator zur Verfügung, der aus dem gleichen Grund wie boost::chrono::time_point_cast()
verwendet werden muss.
boost::chrono::duration_cast()
#include <boost/chrono.hpp>
#include <iostream>
using namespace boost::chrono;
int main()
{
minutes m{1};
seconds s{35};
std::cout << m + s << '\n';
std::cout << duration_cast<minutes>(m + s) << '\n';
}
Im Beispiel 37.4 kommt die Funktion boost::chrono::duration_cast()
zum Einsatz, um einen Zeitraum in Sekunden in einen Zeitraum in Minuten umzuwandeln. Das Beispielprogramm gibt entsprechend 1 minute
aus.
#include <boost/chrono.hpp>
#include <iostream>
using namespace boost::chrono;
int main()
{
std::cout << floor<minutes>(minutes{1} + seconds{45}) << '\n';
std::cout << round<minutes>(minutes{1} + seconds{15}) << '\n';
std::cout << ceil<minutes>(minutes{1} + seconds{15}) << '\n';
}
Boost.Chrono bietet neben boost::chrono::duration_cast()
Funktionen an, um Zeiträume beim Casten zu runden. boost::chrono::round()
rundet automatisch auf oder ab. boost::chrono::floor()
rundet immer ab, boost::chrono::ceil()
immer auf. boost::chrono::floor()
verwendet boost::chrono::duration_cast()
– es gibt keinen Unterschied zwischen diesen beiden Funktionen.
Beispiel 37.5 gibt 1 minute
, 1 minute
und 2 minutes
auf die Standardausgabe aus.
#define BOOST_CHRONO_VERSION 2
#include <boost/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>
#include <iostream>
using namespace boost::chrono;
int main()
{
std::cout << symbol_format << minutes{10} << '\n';
std::cout << time_fmt(boost::chrono::timezone::local, "%H:%M:%S") <<
system_clock::now() << '\n';
}
Boost.Chrono bietet verschiedene Stream-Manipulatoren, um die Ausgabe von Zeiträumen und -punkten zu formatieren. So kann der Manipulator boost::chrono::symbol_format()
verwendet werden, um die Zeiteinheit mit einem Symbol anstatt mit einem ausgeschriebenen Namen anzugeben. Im Beispiel 37.6 wird entsprechend 10 min
ausgegeben.
Der Manipulator boost::chrono::time_fmt()
kann verwendet werden, um sowohl eine Zeitzone als auch eine Formatierung festzulegen. Die Zeitzone muss entweder boost::chrono::timezone::local
oder boost::chrono::timezone::utc
sein. Die Formatierung ist ein String, in dem mit verschiedenen Kürzeln auf die einzelnen Bestandteile eines Zeitpunkts Bezug genommen wird. So wird im Beispiel 37.6 zum Beispiel 15:46:44
ausgegeben.
Neben Stream-Manipulatoren bietet Boost.Chrono auch zahlreiche Facets. So können Sie mit ihrer Hilfe zum Beispiel Zeiteinheiten in einer anderen Sprache ausgeben.
Beachten Sie, dass die Input/Output-Funktionen seit Boost 1.52.0 in zwei Versionen vorliegen. Seit Boost 1.55.0 wird standardmäßig die neue Version verwendet. Verwenden Sie eine ältere Version als 1.55.0, müssen Sie wie im Beispiel geschehen das Makro BOOST_CHRONO_VERSION
definieren und auf 2 setzen.