Вопрос

I'm on a 64bit Ubuntu 12.04 system and tried the following code:

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


int
main(void)
{
  struct timespec user1,user2;
  struct timespec sys1,sys2;
  double user_elapsed;
  double sys_elapsed;

  clock_gettime(CLOCK_REALTIME, &user1);
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &sys1);
  sleep(10);
  clock_gettime(CLOCK_REALTIME, &user2);
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &sys2);
  user_elapsed = user2.tv_sec + user2.tv_nsec/1E9;
  user_elapsed -= user1.tv_sec + user1.tv_nsec/1E9;
  printf("CLOCK_REALTIME: %f\n", user_elapsed);
  sys_elapsed = sys2.tv_sec + sys2.tv_nsec/1E9;
  sys_elapsed -= sys1.tv_sec + sys1.tv_nsec/1E9;
  printf("CLOCK_PROCESS_CPUTIME_ID: %f\n", sys_elapsed);
}

As I understand it, this should print something like

CLOCK_REALTIME: 10.000117
CLOCK_PROCESS_CPUTIME_ID: 10.001

But in my case, what I get is

CLOCK_REALTIME: 10.000117
CLOCK_PROCESS_CPUTIME_ID: 0.000032

Is this the correct behaviour? If so how I can I determine the actual seconds of sys1 and sys2?

When I change CLOCK_PROCESS_CPUTIME_ID to CLOCK_REALTIME then I get the expected result, but that's not what I want because we need the precision.

[EDIT] Apparently CLOCK_PROCESS_CPUTIME_ID returns the actual time the cpu spent on prcessing. CLOCK_MONOTONIC seems to return the right value. But at what precision?

Это было полезно?

Решение

Basically all we need is to precisely get the current running time of the application in microseconds.

Running time here means elapsed time, if I don't misunderstand. Normally, CLOCK_REALTIME is good for that, but if the time is set during the run of the application, CLOCK_REALTIME's notion of elapsed time changes too. To prevent that - unlikely as it may be - I suggest using CLOCK_MONOTONIC or, if present, CLOCK_MONOTONIC_RAW. From the description in the man page

   CLOCK_REALTIME
          System-wide real-time clock.  Setting this clock requires appro-
          priate privileges.

   CLOCK_MONOTONIC
          Clock that cannot be set and  represents  monotonic  time  since
          some unspecified starting point.

   CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
          Similar  to  CLOCK_MONOTONIC, but provides access to a raw hard-
          ware-based time that is not subject to NTP adjustments.

CLOCK_MONOTONIC may be influenced by NTP adjustments, while CLOCK_MONOTONIC_RAW isn't. All these clocks typically have a resolution of one nanosecond (check that with clock_getres()), but for your purposes a resolution below one microsecond would suffice.

To calculate elapsed time in microseconds

#define USED_CLOCK CLOCK_MONOTONIC // CLOCK_MONOTONIC_RAW if available
#define NANOS 1000000000LL

int main(int argc, char *argv[]) {
    /* Whatever */
    struct timespec begin, current;
    long long start, elapsed, microseconds;
    /* set up start time data */
    if (clock_gettime(USED_CLOCK, &begin)) {
        /* Oops, getting clock time failed */
        exit(EXIT_FAILURE);
    }
    /* Start time in nanoseconds */
    start = begin.tv_sec*NANOS + begin.tv_nsec;

    /* Do something interesting */

    /* get elapsed time */
    if (clock_gettime(USED_CLOCK, &current)) {
        /* getting clock time failed, what now? */
        exit(EXIT_FAILURE);
    }
    /* Elapsed time in nanoseconds */
    elapsed = current.tv_sec*NANOS + current.tv_nsec - start;
    microseconds = elapsed / 1000 + (elapsed % 1000 >= 500); // round up halves

    /* Display time in microseconds or something */

    return EXIT_SUCCESS;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top