LinuxQuestions.org how to calculate time difference in milliseconds in C/C++
 Programming This forum is for all programming questions. The question does not have to be directly related to Linux and any language is fair game.

Notices

 03-12-2009, 11:52 AM #1 waqasdaar Member   Registered: Jan 2009 Location: Stockholm Sweden Distribution: Ubuntu 9.10 Posts: 57 Rep: how to calculate time difference in milliseconds in C/C++ Hi I want to calculate the time difference between two events in C++ in milliseconds. I am using difftime which returns me the time in seconds. but I want to calculate the time in milliseconds. Please help me. Because problem is that time difference between two events is mostly is zero seconds. But I want more precision in milliseconds. Thanks in Advanced, Waqas Daar
 03-12-2009, 12:40 PM #2 wje_lq Member   Registered: Sep 2007 Location: Mariposa Distribution: FreeBSD,Debian wheezy Posts: 811 Rep: You are using time() to get the time of day at the beginning of the interval and at its end, correct? Use gettimeofday() for this instead. That puts the time of day in something of type struct timeval, which you will find defined by doing this at the command line: Code: `man gettimeofday` Then do the obvious arithmetic.
 03-12-2009, 06:18 PM #3 graemef Senior Member   Registered: Nov 2005 Location: Hanoi Distribution: Fedora 13, Ubuntu 10.04 Posts: 2,379 Rep: For an OS agnostic approach you could use the Boost libraries, but there is nothing defined in the C++ standard to help you.
 03-13-2009, 04:31 PM #4 jiml8 Senior Member   Registered: Sep 2003 Posts: 3,171 Rep: Code: ```#include struct timeval starttime,endtime,timediff; gettimeofday(&starttime,0x0); (etc) gettimeofday(&endtime,0x0); timeval_subtract(&timediff,&endtime,&starttime); int timeval_subtract (result, x, y) struct timeval *result, *x, *y; { /* Perform the carry for the later subtraction by updating y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (y->tv_usec - x->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; }```
03-14-2009, 10:16 AM   #5
wje_lq
Member

Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep:
Um, jiml8? Your code seems incomplete. (I've tucked a copy of it at the end of this post.) As it stands, it's not clear what sort of int value is supposed to be returned by timeval_subtract(), and in any event your sample calling code at the beginning doesn't use that value at all. But the function also doesn't even use its parameter result in any way, which is puzzling.

I'd like to see jiml8's full code. In the meantime, here's another way to do it. I suspect the guts of the code (in red, ewwww) are simpler than jiml8's will end up being, which is always better if it's at least as fast and just as accurate. But, um, time will tell.

Here's my code, complete with sample calling code.
Code:
```#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

long long
timeval_diff(struct timeval *difference,
struct timeval *end_time,
struct timeval *start_time
)
{
struct timeval temp_diff;

if(difference==NULL)
{
difference=&temp_diff;
}

difference->tv_sec =end_time->tv_sec -start_time->tv_sec ;
difference->tv_usec=end_time->tv_usec-start_time->tv_usec;

/* Using while instead of if below makes the code slightly more robust. */

while(difference->tv_usec<0)
{
difference->tv_usec+=1000000;
difference->tv_sec -=1;
}

return 1000000LL*difference->tv_sec+
difference->tv_usec;

} /* timeval_diff() */

int
main(void)
{
struct timeval earlier;
struct timeval later;
struct timeval interval;

/*
* There are two ways to call timeval_diff.  The first way simply returns
* the time difference as microseconds, a single integer.
*/

if(gettimeofday(&earlier,NULL))
{
perror("first gettimeofday()");

exit(1);
}

sleep(3);

if(gettimeofday(&later,NULL))
{
perror("second gettimeofday()");

exit(1);
}

printf("difference is %lld microseconds\n",
timeval_diff(NULL,&later,&earlier)
);

/*
* The second way to call timeval_diff returns the difference broken down as
* seconds and microseconds.
*/

if(gettimeofday(&earlier,NULL))
{
perror("third gettimeofday()");

exit(1);
}

sleep(4);

if(gettimeofday(&later,NULL))
{
perror("fourth gettimeofday()");

exit(1);
}

timeval_diff(&interval,&later,&earlier);

printf("difference is %ld seconds, %ld microseconds\n",
interval.tv_sec,
interval.tv_usec
);

/*
* Well, actually there's a third way.  You can actually combine the first
* two ways.
*/

if(gettimeofday(&earlier,NULL))
{
perror("fifth gettimeofday()");

exit(1);
}

sleep(5);

if(gettimeofday(&later,NULL))
{
perror("sixth gettimeofday()");

exit(1);
}

printf("difference is %lld microseconds",
timeval_diff(&interval,&later,&earlier)
);

printf(" (%ld seconds, %ld microseconds)\n",
interval.tv_sec,
interval.tv_usec
);

return 0;

} /* main() */```
Sample output:
Code:
```difference is 3002435 microseconds
difference is 4 seconds, 841 microseconds
difference is 5002351 microseconds (5 seconds, 2351 microseconds)```
You want the time in milliseconds? Divide the function result by 1000.

Here's jiml8's code so far:
Quote:
 Originally Posted by jiml8 Code: ```#include struct timeval starttime,endtime,timediff; gettimeofday(&starttime,0x0); (etc) gettimeofday(&endtime,0x0); timeval_subtract(&timediff,&endtime,&starttime); int timeval_subtract (result, x, y) struct timeval *result, *x, *y; { /* Perform the carry for the later subtraction by updating y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (y->tv_usec - x->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; }```

Last edited by wje_lq; 03-14-2009 at 10:18 AM. Reason: typo

 03-15-2009, 10:31 AM #6 jiml8 Senior Member   Registered: Sep 2003 Posts: 3,171 Rep: Oops! I lifted the code out of a working project of mine, and stopped copying at the wrong right brace. Code: ```int timeval_subtract (result, x, y) struct timeval *result, *x, *y; { /* Perform the carry for the later subtraction by updating y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (y->tv_usec - x->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } /* Compute the time remaining to wait. tv_usec is certainly positive. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec; }```
 03-15-2009, 01:17 PM #7 wje_lq Member   Registered: Sep 2007 Location: Mariposa Distribution: FreeBSD,Debian wheezy Posts: 811 Rep: battle of the banjos Comparison of the two functions:His modifies one of the inputs; mine leaves them alone. Both of them return a struct with the difference. Mine also returns the difference as a single integer, a potential convenience for some users. As the value of the function, his returns a warning if the "later" time is actually earlier. In some situations, that could be a huge plus. Which function is faster? I was skeered of those division operations in his function, but I ran some timing tests, and the results are pretty much a wash. In some runs his function was faster; in some, mine. Incidentally, running timing tests on these elapsed time measurement functions gave me a feeling that surely must be similar to finding myself being slowly lowered into a shielded box containing a geiger counter, a very weak source of radioactivity, a flask of hydrocyanic acid, and supporting materials from the hardware store up the street. Last edited by wje_lq; 03-15-2009 at 06:11 PM. Reason: typo
 03-16-2009, 09:47 AM #8 jiml8 Senior Member   Registered: Sep 2003 Posts: 3,171 Rep: I needed the input data only for this computation so didn't worry about changing it. If that is an issue, copying the data would only take a few clock cycles.
03-17-2009, 07:00 AM   #9
Biddle
Member

Registered: Jan 2009
Posts: 37

Rep:
The difference between wje_lq's code and jiml8's code (lets just call it jims code for the time being) is that jims is bullet proof where as wje_lq's is not. There are systems where tv_sec is unsigned and this is where the code would fail.
Quote:
 I lifted the code out of a working project of mine
That is not the only place you lifted if from.

03-17-2009, 10:12 AM   #10
wje_lq
Member

Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep:
Quote:
 Originally Posted by Biddle The difference between wje_lq's code and jiml8's code (lets just call it jims code for the time being) is that jims is bullet proof where as wje_lq's is not. There are systems where tv_sec is unsigned and this is where the code would fail.
I'd prefer to call it jim's code, but maybe that's just me. :)

I'm guessing that you got the tv_sec information (which is useful, by the way, thank you) from the link that you provided:
Quote:
 Here is the best way to do this. It works even on some peculiar operating systems where the tv_sec member has an unsigned type.
But, see, making tv_sec unsigned will not invalidate my code. You'd have to make tv_usec unsigned to do that.

03-17-2009, 10:16 AM   #11
wje_lq
Member

Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep:
Quote:
 Originally Posted by Biddle That is not the only place you lifted if from.
I'm going to stick my neck out here. Some people might read this as a gentle assertion that jiml8 was claiming original authorship, even though Biddle might not have meant to say that he was claiming that. And I don't think he was. He was describing not its ultimate source, but the process during which he erred in copying the code to this thread.

Least-wise, that's my guess.

03-17-2009, 10:29 AM   #12
jiml8
Senior Member

Registered: Sep 2003
Posts: 3,171

Rep:
Quote:
 Originally Posted by Biddle The difference between wje_lq's code and jiml8's code (lets just call it jims code for the time being) is that jims is bullet proof where as wje_lq's is not. There are systems where tv_sec is unsigned and this is where the code would fail. That is not the only place you lifted if from.
You are probably right about that. I've used the code for awhile, and don't/didn't recall where it came from though from the style I knew I hadn't originally written it.

03-17-2009, 10:30 AM   #13
jiml8
Senior Member

Registered: Sep 2003
Posts: 3,171

Rep:
Quote:
 Originally Posted by wje_lq I'm going to stick my neck out here. Some people might read this as a gentle assertion that jiml8 was claiming original authorship, even though Biddle might not have meant to say that he was claiming that. And I don't think he was. He was describing not its ultimate source, but the process during which he erred in copying the code to this thread. Least-wise, that's my guess.
yup.

03-17-2009, 12:04 PM   #14
Biddle
Member

Registered: Jan 2009
Posts: 37

Rep:
Quote:
 Originally Posted by wje_lq I'd prefer to call it jim's code, but maybe that's just me. :)
I was just making people aware of the origin and why the code is as it is, maybe a little sarcastically.

Quote:
 But, see, making tv_sec unsigned will not invalidate my code. You'd have to make tv_usec unsigned to do that.
This is not true, see the following line
Code:
`difference->tv_sec =end_time->tv_sec -start_time->tv_sec ;`
If end is earlier the start and tv_sec is unsigned then the result will be huge and incorrect, yet not in the jims code. Like I said it is bullet proof and coded that way for a reason.

Last edited by Biddle; 03-17-2009 at 12:07 PM.

03-17-2009, 12:42 PM   #15
wje_lq
Member

Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep:
Quote:
 Originally Posted by Biddle I was just making people aware of the origin and why the code is as it is, maybe a little sarcastically.
And I was making a gratuitous, completely unsportsmanlike reference to the lack of the apostrophe one would have expected in the possessive adjective "jim's". Sometimes I hate myself. ;)
Quote:
Originally Posted by Biddle
Quote:
 Originally Posted by wje_lq But, see, making tv_sec unsigned will not invalidate my code. You'd have to make tv_usec unsigned to do that.
This is not true, see the following line
Code:
`difference->tv_sec =end_time->tv_sec -start_time->tv_sec ;`
If end is earlier the start and tv_sec is unsigned then the result will be huge and incorrect, yet not in the jims code. Like I said it is bullet proof and coded that way for a reason.
I had not considered the situation where earlier was actually later. In that case, having an unsigned tv_sec yields a huge and incorrect result in both jiml8's code and mine.

To see that, let's revisit his code after redefining struct timeval to have an unsigned member tv_sec, shall we? And treat it as unsigned throughout.

Run this bash script:
Code:
```#!/bin/bash

cat > 7.c <<EOD

#include <stdio.h>

typedef struct timeval
{
unsigned int tv_sec;
signed   int tv_usec;

} xxx;

int timeval_subtract (result, x, y)
struct timeval *result, *x, *y;
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}

/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;

/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}

int
main(int    argc,
char **argv
)
{
struct timeval difference;
struct timeval earlier;
struct timeval later;

/* ... but we'll make "earlier" contain a value later than "later". */

earlier.tv_sec=5;
earlier.tv_usec=0;

later.tv_sec=3;
later.tv_usec=0;

timeval_subtract(&difference,&later,&earlier);

printf("%ud sec, %d usec\n",difference.tv_sec,difference.tv_usec);

return 0;

} /* main() */
EOD
gcc -Wall 7.c -o 7
./7```
On a system with four-byte ints, you'll get this output:
Code:
`4294967294d sec, 0 usec`
Edit: Note the typo using ud in the printf() statement. The d shouldn't be there, and shows up as extra noise in the output. I believe, though, that this does not invalidate my point.

Last edited by wje_lq; 03-17-2009 at 12:53 PM.

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is Off HTML code is Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post charubcl Linux - Newbie 2 08-08-2008 05:28 AM davidguygc Programming 2 04-25-2007 06:03 PM nickleus Linux - General 3 05-12-2006 10:08 PM syseeker Programming 1 05-04-2006 07:15 AM bndpatel Linux - General 1 06-14-2005 11:25 AM

LinuxQuestions.org

All times are GMT -5. The time now is 01:20 PM.

 Contact Us - Advertising Info - Rules - Privacy - LQ Merchandise - Donations - Contributing Member - LQ Sitemap -