资源开销

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

目前支持的开销如下:

  • 时间开销

头文件

#include "mln_span.h"

模块名

span

函数/宏

mln_span_start

mln_span_start();

描述:开始进行测量。这个宏函数中会对模块使用的全局变量进行设置,并且在测量过程中会仅跟踪调用该函数的线程所调用的函数。

注意:这个宏函数需要与mln_span_stop宏函数在统一作用域内调用,或者mln_span_stop调用点的调用栈深度应大于mln_span_start调用点的调用栈深度。举例:

如果有如下三个函数:mainfoobar。他们之间的调用关系如下:

void bar(void)
{
}
void foo(void)
{
  bar();
}
int main(void)
{
  foo();
  return 0;
}

那么假设mln_span_startfoobar调用前被调用,那么mln_span_stop应该在foomln_span_start之后或者在bar函数中调用,但不能在main中调用。

如果不遵守上述规则,则可能出现内存泄漏的情况。

返回值:无

mln_span_stop

mln_span_stop();

描述:停止进行测量。这个宏函数会销毁部分模块内的全局变量内容,但会保留此次测量中包含测量值的结构。这个宏函数的调用时机参考mln_span_start中的描述。

返回值:无

mln_span_release

mln_span_release();

描述:释放本次测量的测量值结构。注意:这个宏函数应在mln_span_stop之后被调用,否则将可能出现内存访问异常。

返回值:无

mln_span_move

mln_span_move();

描述:获取本次测量的测量值结构,并将指向该结构的全局指针置NULL注意:这个宏函数应在mln_span_stop之后被调用,否则将出现不可预知的错误。

返回值:mln_span_t指针

mln_span_dump

void mln_span_dump(mln_span_dump_cb_t cb, void *data);

typedef void (*mln_span_dump_cb_t)(mln_span_t *s, int level, void *data);

描述:使用用户定义的输出函数和辅助数据,来输出当前测量的数据。其中,mln_span_dump_cb_t的各个参数含义如下:

  • s 当前遍历到的span结点指针

  • level 当前span所处调用栈层级(相对mln_span_start所在的函数调用而言)

  • data 用户自定义数据

返回值:无

mln_span_free

void mln_span_free(mln_span_t *s);

描述:释放mln_span_t结构内存。

返回值:无

mln_span_file

mln_span_file(s);

描述:获取指定span所在文件的文件名。

返回值:char *文件名指针

mln_span_func

mln_span_func(s);

描述:获取指定span所针对的函数名。

返回值:char *函数名指针

mln_span_line

mln_span_line(s);

描述:获取指定span所针对的文件行数。

返回值:int类型文件行数

mln_span_time_cost

mln_span_time_cost(s);

描述:获取指定span所测量的耗时时长,以微秒为单位。

返回值:mln_u64_t微秒数

示例

这是一个多线程的示例,用来展示mln_span接口的使用以及在多线程环境下的效果。

//a.c
#include <pthread.h>
#include "mln_span.h"
#include "mln_func.h"
#include "mln_log.h"

static void mln_span_dump_callback(mln_span_t *s, int level, void *data)
{
    int i;
    for (i = 0; i < level * 2; ++i) {
        mln_log(none, " ");
    }

    mln_log(none, "| %s at %s:%d takes %U (us)\n", \
            mln_span_func(s), mln_span_file(s), mln_span_line(s), mln_span_time_cost(s));
}

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_dump_callback, NULL);
    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;
}

编译程序:

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

执行后可以看到如下输出:

| pentry at a.c:32 takes 16 (us)
  | cde at a.c:25 takes 2 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 3 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 1 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 1 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 1 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 1 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 1 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 3 (us)
    | bcd at a.c:21 takes 2 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 1 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 1 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
  | cde at a.c:25 takes 1 (us)
    | bcd at a.c:21 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)
    | bcd at a.c:21 takes 1 (us)
      | abc at a.c:17 takes 0 (us)
      | abc at a.c:17 takes 0 (us)

results matching ""

    No results matching ""