1 // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and
2 // other Axom Project Developers. See the top-level LICENSE file for details.
3 //
4 // SPDX-License-Identifier: (BSD-3-Clause)
5 
6 /*!
7  ******************************************************************************
8  * \file Timer.hpp
9  *
10  * \brief Defines a simple Timer class to measure execution time.
11  *
12  ******************************************************************************
13  */
14 
15 #ifndef TIMER_HPP_
16 #define TIMER_HPP_
17 
18 #include "axom/config.hpp"
19 
20 #include <chrono>
21 
22 namespace axom
23 {
24 namespace utilities
25 {
26 /*!
27  * \brief A simple Timer class to measure execution time.
28  *
29  *  \note We might want to extend the functionality of the timer class
30  *   by making HighPrecisionTimer a template parameter.
31  *        API requirements for HighPrecisionTimer class
32  *        -- must be default constructible
33  *        -- timing functions:
34  *              void start()
35  *              void stop()
36  *              void reset()
37  *        -- elapsed time functions:
38  *              double elapsedTimeInSec()
39  *              double elapsedTimeInMilliSec()
40  *              double elapsedTimeInMicroSec()
41  *
42  *  \note We might want to add support for pausing and resuming the timer while
43  *    accumulating the time differences
44  *
45  *  Example Usage:
46  *  \code
47  *
48  *     utilities::Timer t;
49  *     t.start();
50  *
51  *     // code to measure its execution time
52  *
53  *     t.stop();
54  *     std::cout << "Elapsed Time: << t.elapsed() << std::endl;
55  *
56  *     t.reset();
57  *
58  *  \endcode
59  */
60 class Timer
61 {
62 private:
63   using ClockType = std::chrono::high_resolution_clock;
64   using TimeStruct = std::chrono::time_point<ClockType>;
65   using TimeDiff = std::chrono::duration<double>;
66   using MilliTimeDiff = std::chrono::duration<double, std::milli>;
67   using MicroTimeDiff = std::chrono::duration<double, std::micro>;
68 
69 public:
70   /*!
71    * \brief Default constructor.
72    * \param startRunning Indicates whether to start the timer
73    *        during construction (default is false)
74    */
Timer(bool startRunning=false)75   Timer(bool startRunning = false) : m_running(startRunning)
76   {
77     if(m_running) start();
78   }
79 
80   /*!
81    * \brief Starts the timer.Sets the start time of this Timer instance.
82    */
start()83   void start()
84   {
85     m_running = true;
86     m_startTime = ClockType::now();
87   }
88 
89   /*!
90    * \brief Stops the timer. Sets the end time of this Timer instance.
91    */
stop()92   void stop()
93   {
94     m_stopTime = ClockType::now();
95     m_running = false;
96   }
97 
98   /*!
99    * \brief Returns the elapsed time in seconds.
100    * \return t the elapsed time in seconds.
101    */
elapsed()102   double elapsed() { return elapsedTimeInSec(); };
103 
104   /*!
105    * \brief Returns the elapsed time in seconds.
106    * \return t the elapsed time in seconds.
107    */
elapsedTimeInSec()108   double elapsedTimeInSec()
109   {
110     if(m_running) stop();
111     return clockDiff().count();
112   }
113 
114   /*!
115    * \brief Returns the elapsed time in milliseconds.
116    * \return t the elapsed time in milliseconds.
117    */
elapsedTimeInMilliSec()118   double elapsedTimeInMilliSec()
119   {
120     if(m_running) stop();
121     return std::chrono::duration_cast<MilliTimeDiff>(clockDiff()).count();
122   }
123 
124   /*!
125    * \brief Returns the elapsed time in microseconds.
126    * \return t the elapsed time in microseconds.
127    */
elapsedTimeInMicroSec()128   double elapsedTimeInMicroSec()
129   {
130     if(m_running) stop();
131     return std::chrono::duration_cast<MicroTimeDiff>(clockDiff()).count();
132   }
133 
134   /*!
135    * \brief Resets the timer.
136    * \post this->elapsed()==0.0
137    */
reset()138   void reset()
139   {
140     m_running = false;
141     m_startTime = m_stopTime = TimeStruct();
142   }
143 
144 private:
145   /*! \brief Computes the difference between start() and stop() */
clockDiff() const146   TimeDiff clockDiff() const { return m_stopTime - m_startTime; }
147 
148   TimeStruct m_startTime;
149   TimeStruct m_stopTime;
150   bool m_running;
151 };
152 
153 }  // namespace utilities
154 }  // namespace axom
155 
156 #endif  // TIMER_HPP_
157