【问题标题】:How to check performance of a function in kernel如何检查内核中函数的性能
【发布时间】:2023-03-10 10:13:01
【问题描述】:

我正在尝试了解和使用现有的实用程序或可编程的 sn-ps,它们可以根据功耗、内核空间中函数的 CPU 周期来测量 CPU 利用率/性能。

我有两个函数 sn-ps 做同样的工作:

将 IP 地址转换为字符串。

char* inet_ntoa(struct in_addr in, char* buf, size_t* rlen)
{

        int i;
        char* bp;

        bp = buf;
        for (i = 0;i < 4; i++ ) {
                unsigned int o, n;
                o = ((unsigned char*)&in)[i];
                n = o;
                if ( n >= 200 ) {
                        *bp++ = '2';
                        n -= 200;
                }else if ( n >= 100 ) {
                        *bp++ = '1';
                        n -= 100;
                }
                if ( o >= 10 ) {
                        int i;
                        for ( i = 0; n >= 10; i++ ) {
                                n -= 10;
                        }
                        *bp++ = i + '0';
                }
                *bp++ = n + '0';
                *bp++ = '.';
        }
        *--bp = 0;
        if ( rlen ) {
                *rlen = bp - buf;
        }

        return buf;
}

char *inet_ntoa (struct in_addr in)
    {
      unsigned char *bytes = (unsigned char *) &in;
      __snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",
              bytes[0], bytes[1], bytes[2], bytes[3]);

      return buffer;
    }

后面的函数来自glibc。前一个是我自己的。

这两个函数将在内核空间中调用。 我如何衡量那里的性能以进行比较。

我的机器是 Ubuntu 14.04 x86 i686。 Linux 内核 3.13

我从源 linux/tools 安装了 perf。

我的模块正在运行。如何挂钩 perf 来衡量我的功能性能。

请多多指教。

【问题讨论】:

  • 为此使用perf 工具。就像在下面提到的答案中一样。

标签: c linux performance linux-kernel perf


【解决方案1】:

您应该查看oprofile。示例输出(来自http://homepages.cwi.nl/~aeb/linux/profile.html

# oprofpp -l -i /foo/vmlinux | tail
c012ca30 488      1.86174     kmem_cache_free
c010e280 496      1.89226     mask_and_ack_8259A
c010a61a 506      1.93041     restore_all
c0119220 603      2.30047     do_softirq
c0110b30 663      2.52938     delay_tsc
c012c7c0 703      2.68198     kmem_cache_alloc
c02146c0 786      2.99863     __copy_to_user_ll
c0169b70 809      3.08637     ext3_readdir
c01476f0 854      3.25805     link_path_walk
c016fcd0 1446     5.51656     ext3_find_entry

【讨论】:

    【解决方案2】:

    您可能会对英特尔工程师的this paper 感兴趣。
    它解释了如何使用 CPU 计时器准确地计时您的代码。

    不要忘记对各种输入进行计时。您可能还需要考虑稳健性方面的潜在差异(您的代码在输入错误时的行为方式)。

    【讨论】:

    • 总结:先禁用抢占和IRQ,然后使用汇编(RDTSC指令)读取代码前后的CPU周期计数器
    • 这是一种有趣的方法,但过于综合。并非总是可以关闭抢占和 IRQ。
    • @SebastianMountaniol 关闭 IRQ 更好,但您不必这样做。在这种情况下,您需要进行多次测试并拒绝突出的高时间(那些被中断的时间)。
    • 有可能,但在这里我们陷入了适当阈值的陷阱。
    【解决方案3】:

    我最近一直在做同样的事情,我正在使用这些工具:

    性能 https://perf.wiki.kernel.org/index.php/Main_Page

    ARM DS5 http://ds.arm.com/

    电源监视器 https://www.msoon.com/LabEquipment/PowerMonitor/

    您可以获得 ARM DS5 的评估版并试用。 它将明智地分析代码应用程序,您可以看到“在线”数据。

    PowerMonitor 已获得许可。

    Perf 是一个非常方便的工具,您可以针对不同的事件进行分析。内核应该针对 perf 事件进行配置。

    它需要开启一些性能分析,可以在内核编译时启用。

    有关 Perf 的相关信息,您可以在此处找到指南: https://perf.wiki.kernel.org/index.php/Tutorial

    【讨论】:

    • 嗨,谢谢你的建议,我已经安装了 perf,但是如何链接 perf 来衡量我的功能性能。
    • 要开始使用,请尝试perf record -a,稍等一下,Ctrl-C,然后运行perf report。确保您的函数实际上被足够频繁地调用,否则它不会显示出来。
    • @maxy 我的函数是否需要导出,尽管我没有在任何其他模块中使用它。 perf 是否只需要导出符号的信息?
    • 您可以找到如何启用对 perf 的支持(如果在附加链接中尚未启用)
    【解决方案4】:

    其他答案为精确测量提供了很好的建议。如果您正在查看粗略的差异,使用timekeeping.h 中的某些内容可能更容易,例如do_gettimeofday

    uint64_t time_one_function(void (*func)(void))
    {   
        const int NUM_ITERATIONS = 5000;
        struct timeval before, after;
    
        do_gettimeofday(&before);
        for (int i = 0; i < NUM_ITERATIONS; i++)
        {
            func();
        }
        do_gettimeofday(&after);
    
        // Time it took to do all iterations in microseconds
        uint64_t diff_microseconds = (after.tv_sec - before.tv_sec) * 1000000ULL + (after.tv_usec - before.tv_usec);
    
        // REturn roughly the time in nanoseconds for a single call
        return (diff_microseconds*1000) / NUM_ITERATIONS;
    }
    

    这将为单个函数提供粗略的纳秒时间,然后在两个函数上调用它。

    【讨论】:

      猜你喜欢
      • 2012-09-11
      • 2018-01-11
      • 2019-06-20
      • 1970-01-01
      • 2019-07-13
      • 2015-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多