How to measure time in milliseconds using ANSI C?

2019-01-01 03:25发布

Using only ANSI C, is there any way to measure time with milliseconds precision or more? I was browsing time.h but I only found second precision functions.

8条回答
ら面具成の殇う
2楼-- · 2019-01-01 04:04
#include <time.h>
clock_t uptime = clock() / (CLOCKS_PER_SEC / 1000);
查看更多
无与为乐者.
3楼-- · 2019-01-01 04:04

The accepted answer is good enough.But my solution is more simple.I just test in Linux, use gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0.

Alse use gettimeofday, the tv_sec is the part of second, and the tv_usec is microseconds, not milliseconds.

long currentTimeMillis() {
  struct timeval time;
  gettimeofday(&time, NULL);

  return time.tv_sec * 1000 + time.tv_usec / 1000;
}

int main() {
  printf("%ld\n", currentTimeMillis());
  // wait 1 second
  sleep(1);
  printf("%ld\n", currentTimeMillis());
  return 0;
 }

It print:

1522139691342 1522139692342, exactly a second.

查看更多
人气声优
4楼-- · 2019-01-01 04:05

There is no ANSI C function that provides better than 1 second time resolution but the POSIX function gettimeofday provides microsecond resolution. The clock function only measures the amount of time that a process has spent executing and is not accurate on many systems.

You can use this function like this:

struct timeval tval_before, tval_after, tval_result;

gettimeofday(&tval_before, NULL);

// Some code you want to time, for example:
sleep(1);

gettimeofday(&tval_after, NULL);

timersub(&tval_after, &tval_before, &tval_result);

printf("Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);

This returns Time elapsed: 1.000870 on my machine.

查看更多
不流泪的眼
5楼-- · 2019-01-01 04:05

I always use the clock_gettime() function, returning time from the CLOCK_MONOTONIC clock. The time returned is the amount of time, in seconds and nanoseconds, since some unspecified point in the past, such as system startup of the epoch.

#include <stdio.h>
#include <stdint.h>
#include <time.h>

int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
  return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
           ((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}

int main(int argc, char **argv)
{
  struct timespec start, end;
  clock_gettime(CLOCK_MONOTONIC, &start);

  // Some code I am interested in measuring 

  clock_gettime(CLOCK_MONOTONIC, &end);

  uint64_t timeElapsed = timespecDiff(&end, &start);
}
查看更多
只靠听说
6楼-- · 2019-01-01 04:08

The best precision you can possibly get is through the use of the x86-only "rdtsc" instruction, which can provide clock-level resolution (ne must of course take into account the cost of the rdtsc call itself, which can be measured easily on application startup).

The main catch here is measuring the number of clocks per second, which shouldn't be too hard.

查看更多
墨雨无痕
7楼-- · 2019-01-01 04:09

timespec_get from C11

Returns up to nanoseconds, rounded to the resolution of the implementation.

Looks like an ANSI ripoff from POSIX' clock_gettime.

Example: a printf is done every 100ms on Ubuntu 15.10:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static long get_nanos(void) {
    struct timespec ts;
    timespec_get(&ts, TIME_UTC);
    return (long)ts.tv_sec * 1000000000L + ts.tv_nsec;
}

int main(void) {
    long nanos;
    long last_nanos;
    long start;
    nanos = get_nanos();
    last_nanos = nanos;
    start = nanos;
    while (1) {
        nanos = get_nanos();
        if (nanos - last_nanos > 100000000L) {
            printf("current nanos: %ld\n", nanos - start);
            last_nanos = nanos;
        }
    }
    return EXIT_SUCCESS;
}

The C11 N1570 standard draft 7.27.2.5 "The timespec_get function says":

If base is TIME_UTC, the tv_sec member is set to the number of seconds since an implementation defined epoch, truncated to a whole value and the tv_nsec member is set to the integral number of nanoseconds, rounded to the resolution of the system clock. (321)

321) Although a struct timespec object describes times with nanosecond resolution, the available resolution is system dependent and may even be greater than 1 second.

C++11 also got std::chrono::high_resolution_clock: C++ Cross-Platform High-Resolution Timer

glibc 2.21 implementation

Can be found under sysdeps/posix/timespec_get.c as:

int
timespec_get (struct timespec *ts, int base)
{
  switch (base)
    {
    case TIME_UTC:
      if (__clock_gettime (CLOCK_REALTIME, ts) < 0)
        return 0;
      break;

    default:
      return 0;
    }

  return base;
}

so clearly:

  • only TIME_UTC is currently supported

  • it forwards to __clock_gettime (CLOCK_REALTIME, ts), which is a POSIX API: http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html

    Linux x86-64 has a clock_gettime system call.

    Note that this is not a fail-proof micro-benchmarking method because:

    • man clock_gettime says that this measure may have discontinuities if you change some system time setting while your program runs. This should be a rare event of course, and you might be able to ignore it.

    • this measures wall time, so if the scheduler decides to forget about your task, it will appear to run for longer.

    For those reasons getrusage() might be a better better POSIX benchmarking tool, despite it's lower microsecond maximum precision.

    More information at: Measure time in Linux - time vs clock vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?

查看更多
登录 后发表回答