V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
monkeyNik
V2EX  ›  C

C 语言函数资源开销可观测性

  •  
  •   monkeyNik · 310 天前 · 1060 次点击
    这是一个创建于 310 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前的文章提及过开源 C 语言库Melon函数模板。使用函数模板来扩展函数功能。

    今天,我们介绍 Melon 中的span组件,使用它来轻松监控函数的调用耗时情况。

    概述

    Melon 中的资源开销( span )组件是用来测量 C 语言函数开销的,这个模块需要配合函数模板模块一同使用,因此也需要定义MLN_FUNC_FLAG才会使得函数模板功能启用,进而实现函数开销的跟踪。

    目前支持的开销如下:

    • 时间开销

    头文件

    #include "mln_span.h"
    

    模块名

    span

    在 Melon 中支持模块选择性编译,因此可以选择指定的模块进行编译,脚本将自行计算该模块所依赖的 Melon 中的其他模块并一同进行编译。

    示例

    下面我们一起看一个多线程的示例,用来展示mln_span接口的使用以及在多线程环境下的效果。

    //a.c
    
    #include <pthread.h>
    #include "mln_span.h"
    #include "mln_func.h"
    
    MLN_FUNC(int, abc, (int a, int b), (a, b), {
        return a + b;
    })
    
    MLN_FUNC(static int, bcd, (int a, int b), (a, b), {
        return abc(a, b) + abc(a, b);
    })
    
    MLN_FUNC(static int, cde, (int a, int b), (a, b), {
        return bcd(a, b) + bcd(a, b);
    })
    
    void *pentry(void *args)
    {
        int i;
        mln_span_start();
        for (i = 0; i < 10; ++i) {
            cde(i, i + 1);
        }
    
        mln_span_stop();
        mln_span_dump();
        mln_span_release();
        return NULL;
    }
    
    int main(void)
    {
        int i;
        pthread_t pth;
    
    
        pthread_create(&pth, NULL, pentry, NULL);
    
        for (i = 0; i < 10; ++i) {
            bcd(i, i + 1);
        }
    
        pthread_join(pth, NULL);
    
        return 0;
    }
    

    前面我们说过,span 组件需要配合函数模板组件一同使用。这里我们使用函数模板组件定义了三个函数abc, bcd, cde

    然后我们在main函数中启动一个线程,并在线程入口函数内,调用mln_span_start开启资源消耗跟踪。然后调用cde函数十次。而在main函数中,在创建线程后,循环调用bcd函数十次,最后等待线程退出,程序结束。

    我们对这段程序进行编译:

    cc -o a a.c -I /usr/local/melon/include/ -L /usr/local/melon/lib/ -lmelon -DMLN_FUNC_FLAG -lpthread
    

    注意,这里-DMLN_FUNC_FLAG是用来启用函数模板模块的功能。如果不定义这个宏,那么使用MLN_FUNC定义的函数就是普通 C 语言函数,不会启用任何跟踪能力。

    编译好后运行程序,可以看到类似如下的输出:

    | pentry at a.c:20 takes 92 (us)
      | cde at a.c:13 takes 4 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
      | cde at a.c:13 takes 5 (us)
        | bcd at a.c:9 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
        | bcd at a.c:9 takes 2 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
      | cde at a.c:13 takes 24 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
        | bcd at a.c:9 takes 21 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
      | cde at a.c:13 takes 5 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
      | cde at a.c:13 takes 3 (us)
        | bcd at a.c:9 takes 2 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
      | cde at a.c:13 takes 30 (us)
        | bcd at a.c:9 takes 24 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 1 (us)
        | bcd at a.c:9 takes 6 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
      | cde at a.c:13 takes 3 (us)
        | bcd at a.c:9 takes 2 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
      | cde at a.c:13 takes 3 (us)
        | bcd at a.c:9 takes 2 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 1 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
      | cde at a.c:13 takes 7 (us)
        | bcd at a.c:9 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
        | bcd at a.c:9 takes 2 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 1 (us)
      | cde at a.c:13 takes 3 (us)
        | bcd at a.c:9 takes 2 (us)
          | abc at a.c:5 takes 1 (us)
          | abc at a.c:5 takes 0 (us)
        | bcd at a.c:9 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
          | abc at a.c:5 takes 0 (us)
    

    最后

    感兴趣的小伙伴欢迎访问Melon 的 Github进行试用。Melon 是一个跨平台的 C 语言库,内含多种数据结构、算法和常用组件。Melon 并不是一个纯粹的数据结构和算法库,而是致力于提供开发中常用的组件,如:内存池、线程池、多进程框架、可观测性等。Melon 提供中英文文档,内含各模块接口说明和示例代码,便于开发者快速上手。

    感谢阅读!

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5889 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 02:57 · PVG 10:57 · LAX 18:57 · JFK 21:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.