如何测量 (linux C) 函数的执行时间?

发布于 2024-09-18 17:18:33 字数 316 浏览 5 评论 0原文

我有一个特定的函数(好吧,函数集),我想每 400 毫秒启动一次。我不是一个 C 程序员,因此标准库之外的任何内容对我来说都是一个谜,其中的很多内容也是如此。

我的第一个想法是使用 nanosleep 在某种循环中暂停执行 400 毫秒,但这当然没有考虑我将要运行的代码的执行时间。如果我可以测量它,并且在 10 或 20 次测试后看起来相当确定它运行了相同的大致持续时间,那么我可以使用 nanosleep() 来计算差异。当然,这并不完美……但对于第一次尝试来说,它可能已经足够接近了。

如何测量 C 函数的执行时间?或者是否有更好的方法来完成此操作,我需要在谷歌上搜索哪些关键字?

I have a particular function (well, set of functions) that I want to start every 400ms. I'm not much of a C programmer, and so anything outside of the standard libraries is a mystery to me, as well as quite a bit within them.

My first thought is to use nanosleep to pause execution for 400ms in some sort of loop, but this of course doesn't take into account the execution time of the code I will be running. If I could measure it, and if it seemed fairly certain that it ran for the same approximate duration after 10 or 20 tests, I could then nanosleep() for the difference. This wouldn't be perfect, of course... but it might be close enough for a first try.

How do I measure the execution time of a C function? Or is there a better way to do this altogether, and what keywords do I need to be googling for?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦里人 2024-09-25 17:18:33

您应该能够使用 settimer

int setitimer(int which, const struct itimerval *value,
              struct itimerval *ovalue);

只需放入您想要每 400 毫秒执行一次的代码在 SIGALRM 处理程序内。这样,您就无需考虑代码运行所需的时间,该时间可能会有所不同。我不确定如果信号处理程序在生成下一个信号之前没有返回会发生什么。

部分代码的概要如下所示。

void periodic_fuc(int signal_num)
{
  ...
  signam(SIGALRM, periodic_func);
}

int main(...)
{
  struct itimerval timerval = {0};

  signal(SIGALRM, periodic_func);      
  ...
  timerval.it_interval.tv_usec = 400000;
  timerval.it_value.tv_usec = 400000; // Wait 400ms for first trigger
  settimer(ITIMER_REAL, &timerval, NULL);

  while (!exit)
    sleep(1);
  return 0;
}

You should be able to use settimer

int setitimer(int which, const struct itimerval *value,
              struct itimerval *ovalue);

Just put the code that you want to execute every 400ms inside the SIGALRM handler. This way you don't need to account for the time that your code takes to run, which could potentially vary. I'm not sure what happens if the signal handler doesn't return before the next signal is generated.

An outline of what some of the code might look like is shown below.

void periodic_fuc(int signal_num)
{
  ...
  signam(SIGALRM, periodic_func);
}

int main(...)
{
  struct itimerval timerval = {0};

  signal(SIGALRM, periodic_func);      
  ...
  timerval.it_interval.tv_usec = 400000;
  timerval.it_value.tv_usec = 400000; // Wait 400ms for first trigger
  settimer(ITIMER_REAL, &timerval, NULL);

  while (!exit)
    sleep(1);
  return 0;
}
中二柚 2024-09-25 17:18:33

查看 gprof。它允许您快速重新编译代码并生成有关正在调用哪些函数以及程序中哪些函数占用最多时间的信息。

Take a look at gprof. It allows you to quickly recompile your code and generate information on which functions are being called and what is taking up the most time in your program.

梦在深巷 2024-09-25 17:18:33

我同意 torak 关于使用 setitimer()。但是,由于尚不清楚当 SIGALRM 处理程序退出时是否重新启动间隔,并且无论如何您都不应该在信号处理程序中做太多工作,所以最好只是让它设置一个标志,并在主例程中完成工作:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>

volatile sig_atomic_t wakeup = 0;

void alarm_handler(int signal_num)
{
    wakeup = 1;
}

int main()
{
    struct itimerval timerval = { 0 };
    struct sigaction sigact = { 0 };
    int finished = 0;

    timerval.it_interval.tv_usec = 400000;
    timerval.it_value.tv_usec = 400000;

    sigact.sa_handler = alarm_handler;

    sigaction(SIGALRM, &sigact, NULL);
    setitimer(ITIMER_REAL, &timerval, NULL);

    while (!finished)
    {
        /* Wait for alarm wakeup */
        while (!wakeup)
            pause();
        wakeup = 0;

        /* Code here... */
        printf("(Wakeup)\n");
    }

    return 0;
}

I concur with torak about using setitimer(). However, since it's not clear if the interval is restarted when the SIGALRM handler exits, and you're really not supposed to do much work in a signal handler anyway, it's better to just have it set a flag, and do the work in the main routine:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>

volatile sig_atomic_t wakeup = 0;

void alarm_handler(int signal_num)
{
    wakeup = 1;
}

int main()
{
    struct itimerval timerval = { 0 };
    struct sigaction sigact = { 0 };
    int finished = 0;

    timerval.it_interval.tv_usec = 400000;
    timerval.it_value.tv_usec = 400000;

    sigact.sa_handler = alarm_handler;

    sigaction(SIGALRM, &sigact, NULL);
    setitimer(ITIMER_REAL, &timerval, NULL);

    while (!finished)
    {
        /* Wait for alarm wakeup */
        while (!wakeup)
            pause();
        wakeup = 0;

        /* Code here... */
        printf("(Wakeup)\n");
    }

    return 0;
}
七堇年 2024-09-25 17:18:33

您可以使用 gettimeofday()clock_gettime() 之前和之后函数来计算时间,然后计算两个时间之间的增量。

You could use gettimeofday() or clock_gettime() before and after the functions to time, and then calculate the delta between the two times.

刘备忘录 2024-09-25 17:18:33

对于 Linux,您可以使用 gettimeofday。在函数开始时调用 gettimeofday。跑任何你必须跑的东西。然后获取结束时间并计算出您还需要睡多长时间。然后调用 usleep 适当的微秒数。

For Linux, you can use gettimeofday. Call gettimeofday at the start of the function. Run whatever you have to run. Then get the end time and figure out how much longer you have to sleep. Then call usleep for the appropriate number of microseconds.

﹉夏雨初晴づ 2024-09-25 17:18:33

看看 POSIX 定时器。以下是HP 的一些文档

您可以执行与 setitimer 相同的功能,但您还可以使用 timer_getoverrun() 来通知您在函数期间是否错过了任何计时器事件。

Look at POSIX timers. Here is some documentation at HP.

You can do the same functions as with setitimer, but you also have timer_getoverrun() to let you know if you missed any timer events during your function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文