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 |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
|
03-12-2009, 12:52 PM
|
#1
|
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, 01:40 PM
|
#2
|
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:
Then do the obvious arithmetic.
|
|
|
03-12-2009, 07:18 PM
|
#3
|
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, 05:31 PM
|
#4
|
Senior Member
Registered: Sep 2003
Posts: 3,171
Rep:
|
Code:
#include <sys/time.h>
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, 11:16 AM
|
#5
|
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 <sys/time.h>
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 11:18 AM.
Reason: typo
|
|
|
03-15-2009, 11:31 AM
|
#6
|
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, 02:17 PM
|
#7
|
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 07:11 PM.
Reason: typo
|
|
|
03-16-2009, 10:47 AM
|
#8
|
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, 08:00 AM
|
#9
|
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, 11:12 AM
|
#10
|
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, 11:16 AM
|
#11
|
Member
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811
Rep:
|
Quote:
Originally Posted by Biddle
|
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, 11:29 AM
|
#12
|
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, 11:30 AM
|
#13
|
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, 01:04 PM
|
#14
|
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 01:07 PM.
|
|
|
03-17-2009, 01:42 PM
|
#15
|
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 01:53 PM.
|
|
|
All times are GMT -5. The time now is 08:02 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|