使用sleep()时计算执行时间

时间:2014-03-26 12:37:47

标签: c linux embedded

我正在尝试从beagle骨中的ADC读取数据,运行Angstrom linux发行版。我需要使用像sleep()这样的延迟机制,只在特定时间读取样本,以帮助符合特定的采样率。     我还需要计算执行时间。

这是一个示例POC(概念证明),用于演示我面临的问题:

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


int main()
{
clock_t begin, end;

    while(1)
    {
        begin = clock();
        sleep(1); // delay for 1 sec
        end = clock();
        printf("Execution time = %f\n",((float)(end-begin)/CLOCKS_PER_SEC));

    }

}

我总是将执行时间设为0.0;

为什么我的结果不是1?我的猜测是调用sleep()会抢占我的程序,但我不确定。

我还有什么其他选择来计算执行时间,包括延迟?

5 个答案:

答案 0 :(得分:3)

计算执行时间的解决方案是在程序开头和结束时获取时间戳。然后有所作为。

#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);
}

编辑:

#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);
}

答案 1 :(得分:3)

Unix

Unix的原始版本不支持亚秒级计时,只有C标准的最新版本支持亚秒级“实时”(又称'wall time'或“经过时间”)。在某个时候,先添加了ftime(),然后依次添加了gettimeofday()clock_gettime(),并且在C90中将clock()函数进行了标准化。

  • C标准以及至少从第7版UNIX™起使用的Unix通过time()函数提供了每秒精度:

    time_t now = time(0);
    
    printf("%ld\n", (long)now);
    
  • 第7版UNIX™(或第7版UNIX™)提供了ftime()的毫秒级分辨率-它已包含在POSIX中,直到2004年版本(ftime())为止,但是它不是POSIX 2008或更高版本的一部分,尽管出于向后兼容性的原因,某些机器类型仍将支持它。

    #include <sys/timeb.h>
    
    struct timeb tb;
    if (ftime(&tb) == 0)
        printf("%ld.%.3d\n", (long)tb.time, tb.millitm);
    
  • POSIX还通过struct timevalgettimeofday()提供(并且仍然提供)微秒分辨率计时。在POSIX 2008中被标记为过时。它可能是最便携的计时器。

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

    请注意,使用gettimeofday()时有一些注意事项-如果有人在连续的通话之间调整系统,其结果可能会受到影响。类似的注释适用于clock_gettime()CLOCK_REALTIME

  • POSIX正在朝着使用纳秒分辨率计时的方向发展,该计时通过struct timespecclock_gettime()提供。使用clock_gettime(),必须选择要测量的时钟。在许多情况下,CLOCK_REALTIME是正确的选择(但如果可用,CLOCK_MONOTONIC在某些情况下可能会更好)。

    #include <time.h>
    
    struct timespec ts;
    if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
        printf("%ld.%.9d\n", (long)ts.tv_sec, ts.tv_nsec);
    
  • 我不确定clock()的确切来源。它不是在第7版Unix中,但在SVR4中是100,用于CLOCKS_PER_SEC。 C标准提供了clock()函数((clock()的POSIX规范要求CLOCKS_PER_SEC需要1,000,000; C不需要)。请注意,这并不测量经过的“墙时间”;它测量的是近似值。进程已使用的CPU时间。

      

    自实现定义的时代开始以来,clock()函数应将实现的最佳近似返回到过程所使用的处理器时间。

         

    要确定以秒为单位的时间,应将clock()返回的值除以宏CLOCKS_PER_SEC的值。 [XSI] ⌦CLOCKS_PER_SEC在<time.h>中定义为一百万。 ⌫

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

    由于clock()函数测量的是CPU使用时间,而不是经过的挂钟时间,因此使用sleep()时测量经过的时间是完全不合适的,因为休眠进程使用 no CPU时间。

  • C11标准提供了一些使用struct timespec的与线程相关的函数,这些函数被定义为与该类型的POSIX定义相匹配。它还提供了功能timespec_get()

      

    7.27.2.5 timespec_get功能

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

    ¶2timespec_get函数设置ts所指向的间隔,以基于指定的时基保存当前的日历时间。

         

    ¶3如果base为TIME_UTC,则将tv_sec成员设置为自实现定义的纪元以来的秒数,将其截断为整个值,并将tv_nsec成员设置为整数纳秒,四舍五入到系统时钟的分辨率。 321)

         

    ¶4如果timespec_get函数成功,它将返回非零值base;否则,它将返回零。

         

    321)尽管struct timespec对象以纳秒分辨率描述时间,但可用分辨率取决于系统,甚至可能大于1秒。

    此功能可能尚未广泛使用。例如,尽管它似乎在OpenBSD中可用,但在macOS 10.14.5 Mojave上不可用。它可能在glibc(GNU C库)中可用,但未在Linux手册页中列出(既不在section 2 system callssection 3 functionshttps://linux.die.net中,也没有在{ {3}}或section 2 system callssection 3 functions)。同样清楚的是,如果clock_gettime()可用,对它实施一个体面的近似值很简单:

    #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提供了其他接口,包括https://man7.org/GetTickCount(),该接口返回自参考时间(最长49天)以来的毫秒数。您可能还会找到对QueryPerformanceCounter()(一种Intel CPU指令)的引用并用于它。

打印time_t

请注意,在整个代码中,我假设可以通过将值转换为time_t并使用long格式来打印%ld值。这对于64位Unix系统是正确的。直到2038年1月,当当前时间与“ The(Unix)Epoch”(1970年1月1日00: 00:00 +00:00)大于2 32 -1秒-32位算术溢出。然后,强制类型转换应为long long(保证至少为64位类型),格式应为%lld。唯一的问题(以及现在不这样做的原因)是MS Visual Studio支持的格式-据我所知,它使用非标准名称和64位类型的格式说明符。

计算经过时间涉及计算这些函数返回的两个值之间的差。轻柔地处理结构;减去时必须处理上溢或下溢。

答案 2 :(得分:2)

确实:在sleep()期间,该计划根本没有运行。并且由于clock()计算CPU时间而不是挂钟时间,&#34;没有时间过去&#34;。

改为使用time()

答案 3 :(得分:0)

clock_gettime是用于此目的的函数。不要使用gettimeofday()...它已被弃用,并且在Opengroup和Linux手册页中有指导AGAINST使用它。

&LT;&LT;

答案 4 :(得分:0)

我使用MACRO打印经过时间。

#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;
}
  

输出:

test_func1:Time elapsed: 1.000103 seconds                                                                             
test_func2:Time elapsed: 2.000974 seconds