Skip to content

Commit 870c4ae

Browse files
committed
ESDK-4087 Addressed perf issue in EmaCppConsPerf.
1 parent 78293fa commit 870c4ae

File tree

9 files changed

+397
-37
lines changed

9 files changed

+397
-37
lines changed
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
///*|-----------------------------------------------------------------------------
2+
// *| This source code is provided under the Apache 2.0 license --
3+
// *| and is provided AS IS with no warranty or guarantee of fit for purpose. --
4+
// *| See the project's LICENSE.md for details. --
5+
// *| Copyright (C) 2019 Refinitiv. All rights reserved. --
6+
///*|-----------------------------------------------------------------------------
7+
8+
#include "GetTime.h"
9+
10+
using namespace perftool::common;
11+
12+
#if defined(_WIN32)
13+
#include <Windows.h>
14+
// Initialize Windows specific static variable
15+
PerfLargeInteger GetTime::FREQ = {0, 0};
16+
bool GetTime::IsTimeInitialized = false;
17+
void GetTime::initFreq()
18+
{
19+
QueryPerformanceFrequency(&GetTime::FREQ);
20+
GetTime::IsTimeInitialized = true;
21+
}
22+
23+
#endif // defined(_WIN32)
24+
25+
// Initialize static members
26+
const double GetTime::TICKS_PER_SECOND = GetTime::initTicksPerSecond();
27+
const double GetTime::TICKS_PER_MILLI = GetTime::initTicksPerMilli();
28+
const double GetTime::TICKS_PER_MICRO = GetTime::initTicksPerMicro();
29+
const double GetTime::TICKS_PER_NANO = GetTime::initTicksPerNano();
30+
31+
32+
// Use the get high resolution time function call.
33+
// This call uses the high resolution timer which is the non-adjustable high-res clock for the system.
34+
// It is not in any way correlated to the time of day.
35+
36+
// Use the clock_gettime to access the clock.
37+
// It is not in any way corrleted to the time of day.
38+
#if defined(Linux) || defined(LINUX)
39+
40+
#include <time.h>
41+
#include <errno.h>
42+
#include <sys/time.h>
43+
44+
double GetTime::initTicksPerSecond()
45+
{
46+
return 1000000000.0;
47+
}
48+
49+
double GetTime::initTicksPerMilli()
50+
{
51+
return 1000000.0;
52+
}
53+
54+
double GetTime::initTicksPerMicro()
55+
{
56+
return 1000.0;
57+
}
58+
59+
double GetTime::initTicksPerNano()
60+
{
61+
return 1.0;
62+
}
63+
64+
PerfTimeValue GetTime::getTimeSeconds()
65+
{
66+
PerfTimeValue ret;
67+
struct timespec ts;
68+
69+
if ( clock_gettime(CLOCK_MONOTONIC,&ts) == 0)
70+
{
71+
ret = (PerfTimeValue)ts.tv_sec + (PerfTimeValue)ts.tv_nsec / 1000000000ULL;
72+
}
73+
else
74+
{
75+
struct timeval tv;
76+
gettimeofday(&tv,0);
77+
ret = (PerfTimeValue)tv.tv_sec + (PerfTimeValue)tv.tv_usec / 1000000ULL;
78+
}
79+
return(ret);
80+
}
81+
82+
PerfTimeValue GetTime::getTimeMilli()
83+
{
84+
PerfTimeValue ret;
85+
struct timespec ts;
86+
87+
if ( clock_gettime(CLOCK_MONOTONIC,&ts) == 0)
88+
{
89+
ret = (PerfTimeValue)ts.tv_sec * 1000ULL + (PerfTimeValue)ts.tv_nsec / 1000000ULL;
90+
}
91+
else
92+
{
93+
struct timeval tv;
94+
gettimeofday(&tv,0);
95+
ret = (PerfTimeValue)tv.tv_sec * 1000ULL + (PerfTimeValue)tv.tv_usec / 1000ULL;
96+
}
97+
return(ret);
98+
}
99+
100+
PerfTimeValue GetTime::getTimeMicro()
101+
{
102+
PerfTimeValue ret;
103+
struct timespec ts;
104+
105+
if ( clock_gettime(CLOCK_MONOTONIC,&ts) == 0)
106+
{
107+
ret = (PerfTimeValue)ts.tv_sec * 1000000ULL + (PerfTimeValue)ts.tv_nsec / 1000ULL;
108+
}
109+
else
110+
{
111+
struct timeval tv;
112+
gettimeofday(&tv,0);
113+
ret = (PerfTimeValue)tv.tv_sec * 1000000ULL + (PerfTimeValue)tv.tv_usec;
114+
}
115+
return(ret);
116+
}
117+
118+
PerfTimeValue GetTime::getTimeNano()
119+
{
120+
PerfTimeValue ret;
121+
struct timespec ts;
122+
123+
if ( clock_gettime(CLOCK_MONOTONIC,&ts) == 0)
124+
{
125+
ret = (PerfTimeValue)ts.tv_sec * 1000000000ULL + (PerfTimeValue)ts.tv_nsec;
126+
}
127+
else
128+
{
129+
struct timeval tv;
130+
gettimeofday(&tv,0);
131+
ret = (PerfTimeValue)tv.tv_sec * 1000000000ULL + (PerfTimeValue)tv.tv_usec * 1000ULL;
132+
}
133+
return(ret);
134+
}
135+
136+
TICKS GetTime::getTicks()
137+
{
138+
TICKS ret;
139+
struct timespec ts;
140+
141+
if(clock_gettime(CLOCK_MONOTONIC,&ts) == 0)
142+
{
143+
ret = (TICKS)ts.tv_sec * 1000000000ULL + (TICKS)ts.tv_nsec;
144+
}
145+
else
146+
{
147+
struct timeval tv;
148+
gettimeofday(&tv,0);
149+
ret = (TICKS)tv.tv_sec * 1000000000ULL + (TICKS)tv.tv_usec * 1000ULL;
150+
}
151+
return(ret);
152+
}
153+
154+
double GetTime::ticksPerSecond(){ return TICKS_PER_SECOND; }
155+
double GetTime::ticksPerMilli() { return TICKS_PER_MILLI; }
156+
double GetTime::ticksPerMicro() { return TICKS_PER_MICRO; }
157+
double GetTime::ticksPerNano() { return TICKS_PER_NANO; }
158+
159+
#endif // defined(Linux) || defined(LINUX)
160+
161+
162+
// Use the cpu clock tick and cpu frequency to calculate the time.
163+
// It is not in any way correlated to the time of day.
164+
#if defined(_WIN32)
165+
166+
double GetTime::initTicksPerSecond()
167+
{
168+
if(!GetTime::IsTimeInitialized)
169+
GetTime::initFreq();
170+
171+
return (double) FREQ.QuadPart;
172+
}
173+
174+
double GetTime::initTicksPerMilli()
175+
{
176+
if(!GetTime::IsTimeInitialized)
177+
GetTime::initFreq();
178+
179+
return (double) FREQ.QuadPart/1000.0;
180+
}
181+
182+
double GetTime::initTicksPerMicro()
183+
{
184+
if(!GetTime::IsTimeInitialized)
185+
GetTime::initFreq();
186+
187+
return (double) FREQ.QuadPart/1000000.0;
188+
}
189+
190+
double GetTime::initTicksPerNano()
191+
{
192+
if(!GetTime::IsTimeInitialized)
193+
GetTime::initFreq();
194+
195+
return (double) FREQ.QuadPart/1000000000.0;
196+
}
197+
198+
PerfTimeValue GetTime::getTimeSeconds()
199+
{
200+
LARGE_INTEGER m_Counter;
201+
double ret;
202+
if ( !QueryPerformanceCounter(&m_Counter) )
203+
return( (PerfTimeValue)0 );
204+
ret = (double)m_Counter.QuadPart / TICKS_PER_SECOND;
205+
return( (PerfTimeValue)ret );
206+
}
207+
208+
PerfTimeValue GetTime::getTimeMilli()
209+
{
210+
LARGE_INTEGER m_Counter;
211+
double ret;
212+
if ( !QueryPerformanceCounter(&m_Counter) )
213+
return( (PerfTimeValue)0 );
214+
ret = (double)m_Counter.QuadPart / TICKS_PER_MILLI;
215+
return( (PerfTimeValue)ret );
216+
}
217+
218+
PerfTimeValue GetTime::getTimeMicro()
219+
{
220+
LARGE_INTEGER m_Counter;
221+
double ret;
222+
if ( !QueryPerformanceCounter(&m_Counter) )
223+
return( (PerfTimeValue)0 );
224+
ret = (double)m_Counter.QuadPart / TICKS_PER_MICRO;
225+
return( (PerfTimeValue)ret );
226+
}
227+
228+
PerfTimeValue GetTime::getTimeNano()
229+
{
230+
LARGE_INTEGER m_Counter;
231+
double ret;
232+
if ( !QueryPerformanceCounter(&m_Counter) )
233+
return( (PerfTimeValue)0 );
234+
ret = (double)m_Counter.QuadPart / TICKS_PER_NANO;
235+
return( (PerfTimeValue)ret );
236+
}
237+
238+
TICKS GetTime::getTicks()
239+
{
240+
LARGE_INTEGER m_Counter;
241+
if ( !QueryPerformanceCounter(&m_Counter) )
242+
return( (TICKS)0 );
243+
return( (TICKS)m_Counter.QuadPart );
244+
}
245+
246+
double GetTime::ticksPerNano()
247+
{
248+
return TICKS_PER_NANO;
249+
}
250+
251+
double GetTime::ticksPerMicro()
252+
{
253+
return TICKS_PER_MICRO;
254+
}
255+
256+
double GetTime::ticksPerMilli()
257+
{
258+
return TICKS_PER_MILLI;
259+
}
260+
261+
double GetTime::ticksPerSecond()
262+
{
263+
return TICKS_PER_SECOND;
264+
}
265+
266+
#endif // defined(_WIN32)
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
///*|-----------------------------------------------------------------------------
2+
// *| This source code is provided under the Apache 2.0 license --
3+
// *| and is provided AS IS with no warranty or guarantee of fit for purpose. --
4+
// *| See the project's LICENSE.md for details. --
5+
// *| Copyright (C) 2019 Refinitiv. All rights reserved. --
6+
///*|-----------------------------------------------------------------------------
7+
8+
#ifndef _GETTIME_H
9+
#define _GETTIME_H
10+
11+
// Interface for efficiently obtaining relative time in various standard units of time.
12+
// Interfaces providing units of seconds, milli seconds, micro seconds, and nano seconds are provided.
13+
// Depending on the platform, the implementation uses clock_gettime(), if available otherwise gettimeofday(), on Linux,
14+
// and QueryPerformanceCounter() on Windows.
15+
16+
// Note that using the nano seconds interface does not necessarily provide nano second resolution or granularity.
17+
// The actual resolution will vary depending on platform and other hardware variables.
18+
// An interface for units of ticks is also provided and gives the time in the smallest units of time and
19+
// the highest resolution available for any given platform.
20+
// However, the actual resolution for any interface can only be determined empirically.
21+
22+
// Interfaces for obtaining the number of ticks per standard unit of time are provided.
23+
// Interfaces for obtaining the absolute time in standard units from two relative times in ticks are provided.
24+
25+
// Note taking the inverse of the number of ticks per standard unit of time can be used to
26+
// determine the upper bound of the actual resolution in the same units of time.
27+
28+
#include "Ema.h"
29+
#if defined(WIN32)
30+
#include <Windows.h>
31+
#define PerfLargeInteger LARGE_INTEGER
32+
#else
33+
#define PerfLargeInteger thomsonreuters::ema::access::Int64
34+
#endif
35+
36+
typedef thomsonreuters::ema::access::UInt64 PerfTimeValue;
37+
typedef thomsonreuters::ema::access::UInt64 TICKS;
38+
39+
namespace perftool {
40+
41+
namespace common {
42+
43+
class GetTime
44+
{
45+
public:
46+
47+
static PerfTimeValue getTimeSeconds();
48+
static PerfTimeValue getTimeMilli();
49+
static PerfTimeValue getTimeMicro();
50+
static PerfTimeValue getTimeNano();
51+
static PerfTimeValue getTicks();
52+
53+
static double ticksPerSecond();
54+
static double ticksPerMilli();
55+
static double ticksPerMicro();
56+
static double ticksPerNano();
57+
58+
static double diffSeconds(TICKS t1, TICKS t2) {return (t2-t1) / ticksPerSecond();}
59+
static double diffMillis(TICKS t1, TICKS t2) {return (t2-t1) / ticksPerMilli();}
60+
static double diffMicros(TICKS t1, TICKS t2) {return (t2-t1) / ticksPerMicro();}
61+
static double diffNanos(TICKS t1, TICKS t2) {return (t2-t1) / ticksPerNano();}
62+
static TICKS diffTicks(TICKS t1, TICKS t2) {return (t2-t1);}
63+
static void initFreq();
64+
static bool getTimeIsInitialized();
65+
private:
66+
static double initTicksPerSecond();
67+
static double initTicksPerMilli();
68+
static double initTicksPerMicro();
69+
static double initTicksPerNano();
70+
71+
static const double TICKS_PER_SECOND;
72+
static const double TICKS_PER_MILLI;
73+
static const double TICKS_PER_MICRO;
74+
static const double TICKS_PER_NANO;
75+
static PerfLargeInteger FREQ;
76+
static bool IsTimeInitialized;
77+
};
78+
79+
80+
inline bool GetTime::getTimeIsInitialized()
81+
{
82+
return GetTime::IsTimeInitialized;
83+
}
84+
85+
} // common
86+
87+
} // perftool
88+
89+
#endif //_GETTIME_H
90+

Cpp-C/Ema/Examples/PerfTools/Common/Statistics.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ bool ResourceUsageStats::initResourceUsageStats()
7272
bool ResourceUsageStats::getResourceUsageStats()
7373
{
7474
Int64 userUsec, kernelUsec;
75-
TimeValue currentTimeUsec;
75+
PerfTimeValue currentTimeUsec;
7676

7777

7878
#if defined(WIN32)
@@ -158,7 +158,7 @@ bool ResourceUsageStats::getResourceUsageStats()
158158
cpuUsageFraction = (double)(userUsec - _prevUserTimeUsec + kernelUsec - _prevKernelTimeUsec);
159159

160160
/* Divide over total time to get the CPU usage as a fraction. */
161-
currentTimeUsec = GetTime::getMicros();
161+
currentTimeUsec = perftool::common::GetTime::getTimeMicro();
162162
cpuUsageFraction /= ((double)(currentTimeUsec - _prevTimeUsec));
163163

164164
_prevUserTimeUsec = userUsec;

0 commit comments

Comments
 (0)