Discussion:
A handy function to use with program timing
Add Reply
DFS
2017-05-16 00:18:22 UTC
Reply
Permalink
Raw Message
In a C program on Linux you might start/stop a timer this way:

clock_gettime(CLOCK_REALTIME,&start);
... do things
clock_gettime(CLOCK_REALTIME,&stop);
elapsed=(stop.tv_sec-start.tv_sec)+
(stop.tv_nsec-start.tv_nsec)/1000000000.0;
printf("elapsed time %.2lfs\n",elapsed);


Windows is similar:

QueryPerformanceCounter(&start);
... do things
QueryPerformanceCounter(&end);
elapsed = (end.QuadPart - start.QuadPart) /
(double)frequency.QuadPart;
printf("elapsed time %.2lfs\n",elapsed);


If you have a lot of program timers it gets clunky. So you can use this
method instead and probably save some lines and make the code more readable.

clock_gettime(CLOCK_REALTIME,&first_timer);
... do things
printf("elapsed time %.2lfs\n",elapsedtime(first_timer);

clock_gettime(CLOCK_REALTIME,&two_timer);
... do things
printf("elapsed time %.2lfs\n",elapsedtime(two_timer);

You can nest timers of course (shown below).

------------------------------------------------------
#include <stdio.h>
#include <time.h>
#include <unistd.h>

struct timespec startmaster,startrows,start,stop;

double elapsedtime(struct timespec starting_timer)
{
const long B = 1000000000.0;
clock_gettime(CLOCK_REALTIME,&stop);
return (stop.tv_sec-starting_timer.tv_sec)+
(stop.tv_nsec-starting_timer.tv_nsec)/B;
}


int main(int argc, char *argv[])
{

int i = 0;

clock_gettime(CLOCK_REALTIME,&startmaster);
printf("Master timer started...\n");

clock_gettime(CLOCK_REALTIME,&startrows);
printf(" Inner timer started...\n");

clock_gettime(CLOCK_REALTIME,&start);
sleep(1);
printf(" 1st timer: %.2lfs\n",elapsedtime(start));

clock_gettime(CLOCK_REALTIME,&start);
for(i=0;i<3;i++)
{
sleep(1);
}
printf(" 2nd timer: %.2lfs\n",elapsedtime(start));

clock_gettime(CLOCK_REALTIME,&start);
sleep(3);
printf(" 3rd timer: %.2lfs\n",elapsedtime(start));

printf(" Inner timer total %.2lfs\n",elapsedtime(startrows));

clock_gettime(CLOCK_REALTIME,&start);
sleep(2);
printf("Another timer: %.2lfs\n",elapsedtime(start));

printf("Master timer total: %.2lfs\n",elapsedtime(startmaster));
return 0;
}
-----------------------------------------------------

What do you C gurus think?
Ben Bacarisse
2017-05-16 12:09:56 UTC
Reply
Permalink
Raw Message
Post by DFS
clock_gettime(CLOCK_REALTIME,&start);
... do things
clock_gettime(CLOCK_REALTIME,&stop);
elapsed=(stop.tv_sec-start.tv_sec)+
(stop.tv_nsec-start.tv_nsec)/1000000000.0;
printf("elapsed time %.2lfs\n",elapsed);
<snip>
Post by DFS
If you have a lot of program timers it gets clunky. So you can use
this method instead...
<snip>
Post by DFS
------------------------------------------------------
#include <stdio.h>
#include <time.h>
#include <unistd.h>
struct timespec startmaster,startrows,start,stop;
double elapsedtime(struct timespec starting_timer)
You might want to pass a pointer here. Not important but it would be
consistent with programmer expectations based on clock_gettime.
Post by DFS
{
const long B = 1000000000.0;
clock_gettime(CLOCK_REALTIME,&stop);
return (stop.tv_sec-starting_timer.tv_sec)+
(stop.tv_nsec-starting_timer.tv_nsec)/B;
This doesn't do what you want because you are not dividing by a floating
point number. You are doing integer division. I would always want to
be working with warning levels set so that I get told about this.

And when you are writing doubles that are just powers of 10, you can use
the clearer form:

const double B = 1e9;
Post by DFS
}
I'd

(a) split this short function up because the calculation is useful on
its own;
(b) use a local timespec;
(c) provide a matching (one-line!) function to start the timer so that
the uses of CLOCK_REALTIME are collect together into the interface;
(d) add a little checking.

bool mark_time(struct timespec *timer)
{
return clock_gettime(CLOCK_REALTIME, timer) == 0;
}

double seconds_between(struct timespec *t1, struct timespec *t2)
{
return t2->tv_sec - t1->tv_sec + (t2_.tv_nsec - t1->tv_nsec)/1e9;
}

double seconds_since(struct timespec *then)
{
struct timespec now;
return mark_time(&now) ? seconds_between(then, &now) : -1;
}

As C11 gets more widely adopted you might consider using timespec_get.
(All this is untested BTW -- consider it a sketch!)

<snip>
--
Ben.
DFS
2017-05-16 18:21:35 UTC
Reply
Permalink
Raw Message
Post by Ben Bacarisse
As C11 gets more widely adopted you might consider using timespec_get.
(All this is untested BTW -- consider it a sketch!)
<snip>
Thanks for the feedback.

Loading...