I am using the C program below (compiled with gcc) to measure the computing time of a given code section.
The issue is that when usleep()
function is used outside the code section being profiled, different measurements are obtained in elapsed_time
.
#include <unistd.h>
#include <stdio.h>
#include <time.h>
int main()
{
int f = 0;
while (f < 10)
{
double sum = 1.0;
struct timespec t0, t1;
clock_gettime(CLOCK_MONOTONIC, &t0);
// CODE SECTION BEING PROFILED
for (unsigned int i = 0; i < 5e6; i++)
sum += 0.001;
// END OF CODE SECTION BEING PROFILED
clock_gettime(CLOCK_MONOTONIC, &t1);
double elapsed_time = t1.tv_sec - t0.tv_sec;
elapsed_time += (t1.tv_nsec - t0.tv_nsec) * 1e-9;
printf("%.2f ms\n", elapsed_time*1000 );
f++;
// Sleep causing fake clock_gettime measurements?
usleep(50000);
}
return 0;
}
Below I paste the result of the programs when uleep(50000)
is commented:
13.83 ms
14.30 ms
14.41 ms
13.77 ms
13.85 ms
13.88 ms
14.55 ms
13.28 ms
13.70 ms
13.56 ms
Now, the results when uleep(50000)
is present:
15.37 ms
14.16 ms
**36.43 ms
39.39 ms
36.38 ms
36.27 ms
34.14 ms
38.52 ms
38.18 ms
37.53 ms**
I tried to measure times with different clocks in clock_gettime()
, and also using the C++ std::chrono::high_resolution_clock
. However, the results are similar in all cases.
Moreover, I tried different gcc flags e.g. O2
. In this case, although much smaller times are obtained, still some measured values when usleep()
is present are ~3x higher than when usleep()
is not present.
I found that the amount of microseconds used in usleep()
affects the resulting measured times, e.g. with 10000us I obtain:
13.75 ms
13.54 ms
13.34 ms
14.15 ms
13.12 ms
12.79 ms
**28.72 ms
25.84 ms
26.18 ms
24.53 ms**
After all theses tests I cannot find what is causing these "fake" time measurements in this program.
Edit:
After some further testing I realized that the same problem is being caused by printf()
(see the code below).
#include <unistd.h>
#include <stdio.h>
#include <time.h>
int main()
{
double total_time = 0.0;
int f = 0;
while (f < 1000)
{
double sum = 1.0;
struct timespec t0, t1;
clock_gettime(CLOCK_MONOTONIC, &t0);
// Code section being profiled
for (unsigned int i = 0; i < 5e6; i++)
sum += 0.001;
// End of Code section being profiled
clock_gettime(CLOCK_MONOTONIC, &t1);
double elapsed_time = t1.tv_sec - t0.tv_sec;
elapsed_time += (t1.tv_nsec - t0.tv_nsec) * 1e-9;
total_time += elapsed_time;
f++;
// Sleep/printf causing fake clock_gettime measurements?
printf("%.2f ms\n", elapsed_time*1000 );
// usleep(10000);
}
printf("TOTAL TIME: %.2f ms\n", total_time*1000 );
return 0;
}
Results
When I run this code compiled with g++ -g
f, I obtain a total time of:
- ~13071.42 ms when line
printf("%.2f ms\n", elapsed_time*1000 );
is present (nota that this line is again outside the section being profiled). - ~12712.22 ms, when that line is commented.
If the program is compiled using optimization (g++ -O2
), I obtain a total time of:
- ~3145.27 ms when that
printf()
is present. - ~2741.45 ms when that
printf()
is not present.
With printf()
the measured times increases to a lesser extent compared to usleep()
. So, the usleep()
doesn't seem to be the only function causing this problem...
Anyway the measured time should not be affected for code placed outside the code section being profiled... Am I missing something?
Edit 2:
The different clocks I tried are:
CLOCK_MONOTONIC_RAW
, CLOCK_PROCESS_CPUTIME_ID
and CLOCK_REALTIME
. All of them offer the same behaviour.
Moreover, I verified the return value of clock_gettime()
to discard failures.