Calculate execution time when sleep() is used

后端 未结 5 1751
难免孤独
难免孤独 2021-01-23 11:30

I am trying to read data from the ADC in the Beagle Bone, running Angstrom Linux distribution. I need to use a delay mechanism like sleep(), to only read samples at

相关标签:
5条回答
  • 2021-01-23 11:52

    Unix

    The original versions of Unix didn't support sub-second timing, and only the latest versions of the C standard support sub-second 'real time' (aka 'wall time' or 'elapsed time'). At some point, ftime() was added, then gettimeofday(), then clock_gettime(), and the clock() function was standardized in C90.

    • The C standard, and Unix since at least 7th Edition UNIX™, has provided single-second accuracy with the time() function:

      time_t now = time(0);
      
      printf("%ld\n", (long)now);
      
    • 7th Edition UNIX™ (or Version 7 UNIX™) provided millisecond resolution with ftime() — and it was included in POSIX up to and including the 2004 version (ftime()), but it is not part of POSIX 2008 or later, though it will still be supported on some machine types for reasons of backwards compatibility.

      #include <sys/timeb.h>
      
      struct timeb tb;
      if (ftime(&tb) == 0)
          printf("%ld.%.3d\n", (long)tb.time, tb.millitm);
      
    • POSIX also provided (and still provides) microsecond resolution timing via struct timeval and gettimeofday(). It is marked obsolescent in POSIX 2008. It may be the most portable timer.

      #include <sys/time.h>
      
      struct timeval tv;
      if (gettimeofday(&tv, NULL) == 0)
          printf("%ld.%.6d\n", (long)tv.tv_sec, tv.tv_usec);
      

      Note that there are caveats about using gettimeofday() — its result can be affected if someone adjusts the system between successive calls. Similar comments apply to clock_gettime() and CLOCK_REALTIME.

    • POSIX is moving towards using nanosecond resolution timing, which is provided via struct timespec and clock_gettime(). With clock_gettime(), you must choose which clock you wish to measure. For many purposes, CLOCK_REALTIME is the correct choice (but CLOCK_MONOTONIC may be better for some purposes, if it is available).

      #include <time.h>
      
      struct timespec ts;
      if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
          printf("%ld.%.9d\n", (long)ts.tv_sec, ts.tv_nsec);
      
    • I'm not sure exactly where clock() came from. It wasn't in 7th Edition Unix, but it was in SVR4 with 100 for CLOCKS_PER_SEC. The C standard provides the clock() function (the POSIX specification for (clock() requires 1,000,000 for CLOCKS_PER_SEC; C does not). Note that this does not measure elapsed 'wall time'; it measures an approximation to the amount of CPU time that a process has used.

      The clock() function shall return the implementation's best approximation to the processor time used by the process since the beginning of an implementation-defined era related only to the process invocation.

      To determine the time in seconds, the value returned by clock() should be divided by the value of the macro CLOCKS_PER_SEC. [XSI] ⌦ CLOCKS_PER_SEC is defined to be one million in <time.h>. ⌫

      clock_t clk = clock();
      
      printf("%.6f\n", (double)clk / CLOCKS_PER_SEC);
      

      Since the clock() function measures the CPU time used, not the wall clock time that elapses, it is wholly inappropriate to measure elapsed time when sleep() is used because a sleeping process uses no CPU time.

    • The C11 standard provides some thread-related functions which use struct timespec, which is defined to match the POSIX definition of the type. It also provides the function timespec_get():

      7.27.2.5 The timespec_get function

          #include <time.h>
          int timespec_get(struct timespec *ts, int base);
      

      ¶2 The timespec_get function sets the interval pointed to by ts to hold the current calendar time based on the specified time base.

      ¶3 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)

      ¶4 If the timespec_get function is successful it returns the nonzero value base; otherwise, it returns zero.

      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.

      This function may not be widely available yet. It is not available on macOS 10.14.5 Mojave, for example, though it seems to be available in OpenBSD. It may be available in glibc (GNU C Library) but it isn't listed in the Linux man pages (neither in section 2 system calls or section 3 functions at https://linux.die.net, nor in section 2 system calls or section 3 functions at https://man7.org/). Equally clearly, it's trivial to implement a decent approximation to it if clock_gettime()is available:

      #if !defined(HAVE_TIMESPEC_GET) && defined(HAVE_CLOCK_GETTIME)
      enum { TIME_UTC = 1 };
      static inline int timespec_get(struct timespec *ts, int base)
      {
          assert(base != 0);
          if (clock_gettime(CLOCK_REALTIME, ts) != 0)
              return 0;
          return base;
      }
      #endif /* HAVE_TIMESPEC_GET */
      

    Windows

    Windows provides alternative interfaces, including GetTickCount() which returns a value in milliseconds since a reference time (valid up to 49 days) and QueryPerformanceCounter(). You may also find references to, and uses for, RDTSC — an Intel CPU instruction.

    Printing time_t values

    Note that throughout this code I've assumed that time_t values can be printed by converting the value to long and using the %ld format. That is correct for 64-bit Unix systems. It is correct for Windows 64-bit, and also for both Unix and Windows 32-bit systems until January 2038, when the value for the gap between the current time and 'The (Unix) Epoch' (1970-01-01 00:00:00 +00:00) grows bigger than 232 - 1 seconds — 32-bit arithmetic overflows. Then the cast type should be long long (which is guaranteed to be at least a 64-bit type) and the format should be %lld. The only issue (and reason for not doing it now) is the formats that MS Visual Studio supports — it uses non-standard names and format specifiers for 64-bit types, as I understand it.

    Calculating elapsed time involves calculating differences between two values returned by these functions. Working with the structures is mildly fiddly; you have to deal with overflows or underflows when subtracting.

    0 讨论(0)
  • 2021-01-23 12:02

    The solution to calculate execution time is to get the timestamp at the beginning of your program and at the end. Then make the difference.

    #include <stdio.h>
    #include <time.h>
    
    int main() {
    
        time_t begin;
        time(&begin);
    
      // Somethings
    
       time_t end;
       time(&end);
    
      printf("Execution time %f\n", difftime(end, begin));
      return (0);
    }
    

    EDIT:

    #include <stdio.h>
    #include <time.h>
    #include <sys/time.h>
    
    int main() {
    
      struct timeval  tv;
      gettimeofday(&tv, NULL);
    
    double begin =
      (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
    
    
     sleep(2);
    
     gettimeofday(&tv, NULL);
    
    double end =
      (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
    
      printf("Execution time %f\n", end - begin);
      return (0);
    }
    
    0 讨论(0)
  • 2021-01-23 12:04

    clock_gettime is the function to use for this purpose. Do not use gettimeofday() ... It is deprecated and there is guidance AGAINST using it from the Opengroup and in Linux man pages.

    <<

    0 讨论(0)
  • 2021-01-23 12:08

    I use MACRO to print the elapse time.

    #include <stdio.h>
    #include <sys/time.h>
    #include <unistd.h>
    #define ELPS_TIME(func_name) do { \
        struct timeval tval_before, tval_after, tval_result; \
        gettimeofday(&tval_before, NULL); \
        func_name; \
        gettimeofday(&tval_after, NULL); \
        timersub(&tval_after, &tval_before, &tval_result); \
        printf("Time elapsed: %ld.%06ld seconds\n", \
            (long int)tval_result.tv_sec, \
            (long int)tval_result.tv_usec); } while(0)
    
    static void test_func1() {
        printf("%s:", __FUNCTION__);
        sleep(1);
    }
    
    static void test_func2() {
        printf("%s:", __FUNCTION__);
        sleep(2);
    }
    
    int main() {
        ELPS_TIME(test_func1()); //calling test_func1 
        ELPS_TIME(test_func2()); //calling test_func2
        return 0;
    }
    

    Output:

    test_func1:Time elapsed: 1.000103 seconds                                                                             
    test_func2:Time elapsed: 2.000974 seconds 
    
    0 讨论(0)
  • 2021-01-23 12:16

    Indeed: during sleep(), the program doesn't run at all. And as clock() counts the CPU time and not the wall clock time, "no time passes".

    Use time() instead.

    0 讨论(0)
提交回复
热议问题