LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
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


Reply
  Search this Thread
Old 03-12-2009, 11:52 AM   #1
waqasdaar
Member
 
Registered: Jan 2009
Location: Stockholm Sweden
Distribution: Ubuntu 9.10
Posts: 57

Rep: Reputation: 15
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
 
Old 03-12-2009, 12:40 PM   #2
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
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.
 
Old 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: Reputation: 148Reputation: 148
For an OS agnostic approach you could use the Boost libraries, but there is nothing defined in the C++ standard to help you.
 
Old 03-13-2009, 04:31 PM   #4
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 116Reputation: 116
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;
  }
 
Old 03-14-2009, 10:16 AM   #5
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
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 View Post
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 10:18 AM. Reason: typo
 
Old 03-15-2009, 10:31 AM   #6
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 116Reputation: 116
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;
}
 
Old 03-15-2009, 01:17 PM   #7
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
battle of the banjos

Comparison of the two functions:
  1. His modifies one of the inputs; mine leaves them alone.
  2. Both of them return a struct with the difference.
  3. Mine also returns the difference as a single integer, a potential convenience for some users.
  4. 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.
  5. 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
 
Old 03-16-2009, 09:47 AM   #8
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 116Reputation: 116
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.
 
Old 03-17-2009, 07:00 AM   #9
Biddle
Member
 
Registered: Jan 2009
Posts: 37

Rep: Reputation: 17
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.
 
Old 03-17-2009, 10:12 AM   #10
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
Quote:
Originally Posted by Biddle View Post
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.
 
Old 03-17-2009, 10:16 AM   #11
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
Quote:
Originally Posted by Biddle View Post
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.
 
Old 03-17-2009, 10:29 AM   #12
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 116Reputation: 116
Quote:
Originally Posted by Biddle View Post
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.
 
Old 03-17-2009, 10:30 AM   #13
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 116Reputation: 116
Quote:
Originally Posted by wje_lq View Post
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.
 
Old 03-17-2009, 12:04 PM   #14
Biddle
Member
 
Registered: Jan 2009
Posts: 37

Rep: Reputation: 17
Quote:
Originally Posted by wje_lq View Post
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.
 
Old 03-17-2009, 12:42 PM   #15
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
Quote:
Originally Posted by Biddle View Post
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 View Post
Quote:
Originally Posted by wje_lq View Post
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.
 
  


Reply



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



Similar Threads
Thread Thread Starter Forum Replies Last Post
Current time in milliseconds charubcl Linux - Newbie 2 08-08-2008 05:28 AM
Time in milliseconds davidguygc Programming 2 04-25-2007 06:03 PM
calculate time difference between 2 formatted timestamps nickleus Linux - General 3 05-12-2006 10:08 PM
C/C++ API for retrieving system time in micro or milliseconds syseeker Programming 1 05-04-2006 07:15 AM
calculate system clock in milliseconds bndpatel Linux - General 1 06-14-2005 11:25 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:50 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration