31

I am trying to measure how long a function takes.

I have a little issue: although I am trying to be precise, and use floating points, every time I print my code using %lf I get one of two answers: 1.000... or 0.000... This leads me to wonder if my code is correct:

#define BILLION  1000000000L;

// Calculate time taken by a request
struct timespec requestStart, requestEnd;
clock_gettime(CLOCK_REALTIME, &requestStart);
function_call();
clock_gettime(CLOCK_REALTIME, &requestEnd);

// Calculate time it took
double accum = ( requestEnd.tv_sec - requestStart.tv_sec )
  + ( requestEnd.tv_nsec - requestStart.tv_nsec )
  / BILLION;
printf( "%lf\n", accum );

Most of this code has not been made by me. This example page had code illustrating the use of clock_gettime:

Could anyone please let me know what is incorrect, or why I am only getting int values please?

Neuron
  • 5,141
  • 5
  • 38
  • 59
Jary
  • 397
  • 1
  • 5
  • 7
  • 12
    No, no, no: don't give names to numbers. Use the function they serve instead: `#define CLOCK_PRECISION 1000000000L /* one billion */` – pmg Oct 15 '10 at 23:51
  • 14
    @pmg: Pedantry tangent: I'd argue that a name such as `CLOCK_PRECISION` would only be necessary if the units were not clear from the variable name. In the case above, it's clear from the name `tv_nsec` that we're in nanoseconds. So `NANOSECONDS_PER_SECOND` might be appropriate, but that's really not a great deal different to simply `BILLION`. – Oliver Charlesworth Oct 15 '10 at 23:57
  • 2
    `CLOCK_REALTIME` is affected by discontinuous jumps in the system time. Consider using `CLOCK_MONOTONIC_RAW` — it is not affected by time adjustments with `adjtime()` and time jumps. – Dmitry Jun 07 '19 at 10:25

4 Answers4

28

Dividing an integer by an integer yields an integer. Try this:

#define BILLION 1E9

And don't use a semicolon at the end of the line. #define is a preprocessor directive, not a statement, and including the semicolon resulted in BILLION being defined as 1000000000L;, which would break if you tried to use it in most contexts. You got lucky because you used it at the very end of an expression and outside any parentheses.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
  • 2
    Thanks a lot for your help. And thanks for letting me know about the semicolon, that is something I forgot. Thank you very much! – Jary Oct 15 '10 at 23:42
  • 2
    For sake of performance.. #define ONE_OVER_BILLION 1E-9 and use multiply. – linleno Jun 05 '16 at 00:38
9

( requestEnd.tv_nsec - requestStart.tv_nsec ) is of integer type, and is always less than BILLION, so the result of dividing one by the other in integer arithmetic will always be 0. You need to cast the result of the subtraction to e.g. double before doing the divide.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1

Note that (requestEnd.tv_nsec - requestStart.tv_nsec) can be negative, in which case you need to subtract 1 second from the tv_sec difference and add one BILLION to the tv_nsec difference.

Wayfarer
  • 19
  • 2
  • Downvote because answer is incorrect. In similar calculations, something like this may be necessary, but not here. If `requestEnd.tv_nsec - requestStart.tv_nsec` is negative and `BILLION` is the double `1E9`, then `(requestEnd.tv_nsec - requestStart.tv_nsec) / BILLION` will be a double between `-1.0` and `0.0`, and adding this number to `(requestEnd.tv_sec - requestStart.tv_sec)` will do the right thing, because the latter is implicitly converted to double. https://en.cppreference.com/w/c/language/conversion – jcsahnwaldt Reinstate Monica Nov 27 '18 at 02:34
1

I know the question was posted long ago, but I still don't see the answer which would suggest you to "convert" elapsed time into nanoseconds (or milliseconds) and not into seconds as in your code sample.

The sample code fragment to illustrate the idea:

long long accum = ( requestEnd.tv_nsec - requestStart.tv_nsec )
 + ( requestEnd.tv_sec - requestStart.tv_sec ) * BILLION;

This way you can avoid floating point arithmetic, which may be heavy for some platforms...

AntonK
  • 1,210
  • 1
  • 16
  • 22