博客 / 詳情

返回

C語言函數資源開銷可觀測性

之前的文章提及過開源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提供中英文文檔,內含各模塊接口説明和示例代碼,便於開發者快速上手。

感謝閲讀!

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.