Skip to content

Commit 4006d81

Browse files
alxbilgerhugtalbot
andauthored
[Helper] Refactor SimpleTimer (#6140)
* SimpleTimer * documentation --------- Co-authored-by: Hugo <hugo.talbot@sofa-framework.org>
1 parent 4682631 commit 4006d81

1 file changed

Lines changed: 55 additions & 107 deletions

File tree

Sofa/framework/Helper/src/sofa/helper/SimpleTimer.h

Lines changed: 55 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -19,137 +19,85 @@
1919
* *
2020
* Contact information: contact@sofa-framework.org *
2121
******************************************************************************/
22-
#ifndef SOFA_HELPER_SIMPLETIMER_H
23-
#define SOFA_HELPER_SIMPLETIMER_H
22+
#pragma once
2423

25-
#include <sofa/helper/system/thread/CTime.h>
24+
#include <chrono>
25+
#include <string>
26+
27+
#include <sofa/helper/logging/Messaging.h>
2628

2729
namespace sofa::helper
2830
{
31+
template<class Unit>
32+
struct UnitInfo;
2933

30-
/**
31-
Very simple timer
32-
33-
Usage example :
34-
35-
sofa::helper::SimpleTimer mytimer;
36-
37-
void myComputationCode() {
38-
39-
bool timer = true; // should I print performance stats
40-
if (timer) mytimer.start("mystep1);
41-
42-
... // step 1 code
43-
44-
if (timer) mytimer.step("mystep2");
34+
template<> struct UnitInfo<std::chrono::nanoseconds>
35+
{
36+
static constexpr std::string_view unit = "ns";
37+
};
4538

46-
... // step 2 code
39+
template<> struct UnitInfo<std::chrono::microseconds>
40+
{
41+
static constexpr std::string_view unit = "us";
42+
};
4743

48-
if (timer) mytimer.stop();
49-
}
44+
template<> struct UnitInfo<std::chrono::milliseconds>
45+
{
46+
static constexpr std::string_view unit = "ms";
47+
};
5048

49+
template<> struct UnitInfo<std::chrono::seconds>
50+
{
51+
static constexpr std::string_view unit = "s";
52+
};
5153

54+
/**
55+
* @class SimpleTimer
56+
* @brief A RAII utility class for measuring elapsed time in operations and log it.
57+
*
58+
* @code
59+
* // Measure a block of code
60+
* {
61+
* sofa::helper::SimpleTimer<std::chrono::milliseconds> timer("File I/O Simulation");
62+
* // ... Simulate file reading/writing here ...
63+
* // The elapsed time is logged by the timer at the end of the scope
64+
* }
65+
* @endcode
5266
*/
53-
54-
template<int nIter=100, int nStep=100>
55-
class TSimpleTimer
67+
template<class Unit = std::chrono::nanoseconds>
68+
struct SimpleTimer
5669
{
57-
public:
58-
59-
enum {T_NSTEPS=nStep, T_NITERS=nIter};
60-
61-
typedef sofa::helper::system::thread::ctime_t ctime_t;
62-
typedef sofa::helper::system::thread::CTime CTime;
63-
64-
ctime_t timer_total;
65-
ctime_t timer_current;
66-
ctime_t timer_freq;
67-
ctime_t timer_start;
68-
ctime_t timers_start;
69-
const char* timers_name[T_NSTEPS];
70-
ctime_t timers_total[T_NSTEPS];
71-
ctime_t timers_current[T_NSTEPS];
72-
int timer_niter;
73-
int timer_nstep;
74-
const char* timer_lastname;
75-
76-
TSimpleTimer()
77-
{
78-
timer_total = 0;
79-
timer_current = 0;
80-
timer_freq = 1;
81-
timer_start = 0;
82-
timers_start = 0;
83-
timer_niter = 0;
84-
timer_nstep = 0;
85-
timer_lastname = "";
86-
}
70+
std::string m_name;
71+
std::chrono::time_point<std::chrono::high_resolution_clock> m_start;
72+
bool hasEnded { false };
73+
74+
explicit SimpleTimer(const std::string& name)
75+
: m_name(name)
76+
, m_start(std::chrono::high_resolution_clock::now())
77+
{}
8778

88-
void start(const char* name)
79+
~SimpleTimer()
8980
{
90-
if (timer_niter == 0)
91-
{
92-
timer_total = 0;
93-
timer_current = 0;
94-
timer_freq = CTime::getTicksPerSec();
95-
for (int i=0; i<T_NSTEPS; ++i) timers_name[i] = "";
96-
for (int i=0; i<T_NSTEPS; ++i) timers_total[i] = 0;
97-
for (int i=0; i<T_NSTEPS; ++i) timers_current[i] = 0;
98-
}
99-
const ctime_t t = CTime::getTime();
100-
timer_start = t;
101-
timers_start = t;
102-
timer_nstep = 0;
103-
timer_lastname = name;
81+
stop();
10482
}
10583

106-
void step(const char* name = "")
84+
void restart()
10785
{
108-
if (timer_nstep >= T_NSTEPS) return;
109-
int i = timer_nstep;
110-
{
111-
timers_name[i] = timer_lastname;
112-
timer_lastname = name;
113-
}
114-
const ctime_t t = CTime::getTime();
115-
timers_current[i] = t - timers_start;
116-
timers_start = t;
117-
timers_total[i] += timers_current[i];
118-
++timer_nstep;
86+
m_start = std::chrono::high_resolution_clock::now();
11987
}
12088

12189
void stop()
12290
{
123-
step();
124-
++timer_niter;
125-
const ctime_t t = CTime::getTime();
126-
timer_current = t - timer_start;
127-
timer_total += timer_current;
128-
timer_start = t;
129-
timers_start = t;
130-
if (timer_niter > 0 && (timer_niter % T_NITERS) == 0)
91+
if (!hasEnded)
13192
{
132-
std::stringstream tmpmsg ;
133-
tmpmsg << "TIMER after " << timer_niter << " iterations :" << msgendl;
134-
for (int i=0; i<T_NSTEPS; ++i)
135-
{
136-
if (timers_total[i])
137-
{
138-
double tcur = 1000.0 * (double)timers_current[i] / (double) timer_freq;
139-
double ttot = 1000.0 * (double)timers_total[i] / (double) (timer_niter * timer_freq);
140-
tmpmsg << " " << i << ". " << timers_name[i] << "\t : " << std::fixed << (tcur < 10 ? " " : tcur < 100 ? " " : tcur < 1000 ? " " : "") << tcur << " \tms ( mean " << (ttot < 10 ? " " : ttot < 100 ? " " : ttot < 1000 ? " " : "") << ttot << " \tms ) " << msgendl;
141-
}
142-
}
143-
double tcur = 1000.0 * (double)timer_current / (double) timer_freq;
144-
double ttot = 1000.0 * (double)timer_total / (double) (timer_niter * timer_freq);
145-
tmpmsg << "** TOTAL *********\t : " << std::fixed << (tcur < 10 ? " " : tcur < 100 ? " " : tcur < 1000 ? " " : "") << tcur << " \tms ( mean " << (ttot < 10 ? " " : ttot < 100 ? " " : ttot < 1000 ? " " : "") << ttot << " \tms ) " ;
146-
msg_info("SimpleTimer") << tmpmsg.str() ;
93+
auto end = std::chrono::high_resolution_clock::now();
94+
msg_info("Timer") << m_name << " took " << std::chrono::duration_cast<Unit>(end - m_start).count() << UnitInfo<Unit>::unit;
95+
hasEnded = true;
14796
}
14897
}
149-
};
15098

151-
typedef TSimpleTimer<> SimpleTimer;
99+
100+
};
152101

153102
}
154103

155-
#endif

0 commit comments

Comments
 (0)