Skip to content

Commit

Permalink
refactor(span): make span module independent of the array and stack m…
Browse files Browse the repository at this point in the history
…odules
  • Loading branch information
Water-Melon committed Feb 2, 2024
1 parent 6a7f59e commit 22f0165
Show file tree
Hide file tree
Showing 7 changed files with 338 additions and 627 deletions.
17 changes: 16 additions & 1 deletion docs/Melon Developer Guide.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3165,12 +3165,27 @@ Their definitions can be found in melon/include/mln_types.h.
d) mln_span_move();
Get span object and reset global variable in span module used by `mln_span_start`.

e) mln_span_dump();
e) void mln_span_dump(mln_span_dump_cb_t cb, void *data);
Dump all information of spans indicated by the global variable in span module.
'cb' is the callback function to process sub-spans whose prototype is:
typedef void (*mln_span_dump_cb_t)(mln_span_t *s, int level, void *data);
'data' is a user data.

f) void mln_span_free(mln_span_t *span);
Free the give span object memory.

g) mln_span_file(s);
Get the filename associated with the span.

h) mln_span_func(s);
Get the function name associated with the span.

i) mln_span_line(s);
Get the file line number associated with the span.

j) mln_span_time_cost(s);
Get the time cost associated with the span.

5. Framework Usage
It is very easy to use this framework. Before we use it, we have to initialize it.
1) include header file.
Expand Down
201 changes: 0 additions & 201 deletions docs/book/cn/func.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,204 +176,3 @@ exit a.c bcd 10
正如`MLN_FUNC`中说明的,使用这个宏定义函数时,实际的函数会被添加`__`前缀,而原本给出的名字则是一个包装器。
### 函数耗时示例
首先创建两个文件`span.c`和`span.h`。
#### span.h
```c
#include <sys/time.h>
#include "mln_array.h"
typedef struct mln_span_s {
struct timeval begin;
struct timeval end;
const char *file;
const char *func;
int line;
mln_array_t subspans;
struct mln_span_s *parent;
} mln_span_t;
extern int mln_span_start(void);
extern void mln_span_stop(void);
extern void mln_span_dump(void);
extern void mln_span_release(void);
```

#### span.c

```c
#include <stdlib.h>
#include <string.h>
#include "span.h"
#include "mln_stack.h"
#define MLN_FUNC_FLAG
#include "mln_func.h"

static mln_stack_t *callstack = NULL;
static mln_span_t *root = NULL;

static void mln_span_entry(const char *file, const char *func, int line);
static void mln_span_exit(const char *file, const char *func, int line);
static mln_span_t *mln_span_new(mln_span_t *parent, const char *file, const char *func, int line);
static void mln_span_free(mln_span_t *s);

static mln_span_t *mln_span_new(mln_span_t *parent, const char *file, const char *func, int line)
{
mln_span_t *s;
struct mln_array_attr attr;

if (parent != NULL) {
s = (mln_span_t *)mln_array_push(&parent->subspans);
} else {
s = (mln_span_t *)malloc(sizeof(mln_span_t));
}
if (s == NULL) return NULL;

memset(&s->begin, 0, sizeof(struct timeval));
memset(&s->end, 0, sizeof(struct timeval));
s->file = file;
s->func = func;
s->line = line;
attr.pool = NULL;
attr.pool_alloc = NULL;
attr.pool_free = NULL;
attr.free = (array_free)mln_span_free;
attr.size = sizeof(mln_span_t);
attr.nalloc = 7;
if (mln_array_init(&s->subspans, &attr) < 0) {
if (parent == NULL) free(s);
return NULL;
}
s->parent = parent;
return s;
}

static void mln_span_free(mln_span_t *s)
{
if (s == NULL) return;
mln_array_destroy(&s->subspans);
if (s->parent == NULL) free(s);
}

int mln_span_start(void)
{
struct mln_stack_attr sattr;

mln_func_entry_callback_set(mln_span_entry);
mln_func_exit_callback_set(mln_span_exit);

sattr.free_handler = NULL;
sattr.copy_handler = NULL;
if ((callstack = mln_stack_init(&sattr)) == NULL)
return -1;

return 0;
}

void mln_span_stop(void)
{
mln_func_entry_callback_set(NULL);
mln_func_exit_callback_set(NULL);
mln_stack_destroy(callstack);
}

void mln_span_release(void)
{
mln_span_free(root);
}

static void mln_span_format_dump(mln_span_t *span, int blanks)
{
int i;
mln_span_t *sub;

for (i = 0; i < blanks; ++i)
printf(" ");
printf("| %s at %s:%d takes %lu (us)\n", \
span->func, span->file, span->line, \
(span->end.tv_sec * 1000000 + span->end.tv_usec) - (span->begin.tv_sec * 1000000 + span->begin.tv_usec));

for (i = 0; i < mln_array_nelts(&(span->subspans)); ++i) {
sub = ((mln_span_t *)mln_array_elts(&(span->subspans))) + i;
mln_span_format_dump(sub, blanks + 2);
}
}

void mln_span_dump(void)
{
if (root != NULL)
mln_span_format_dump(root, 0);
}

static void mln_span_entry(const char *file, const char *func, int line)
{
mln_span_t *span;

if ((span = mln_span_new(mln_stack_top(callstack), file, func, line)) == NULL) {
fprintf(stderr, "new span failed\n");
exit(1);
}
if (mln_stack_push(callstack, span) < 0) {
fprintf(stderr, "push span failed\n");
exit(1);
}
if (root == NULL) root = span;
gettimeofday(&span->begin, NULL);
}

static void mln_span_exit(const char *file, const char *func, int line)
{
mln_span_t *span = mln_stack_pop(callstack);
if (span == NULL) {
fprintf(stderr, "call stack crashed\n");
exit(1);
}
gettimeofday(&span->end, NULL);
}
```
接下来,创建一个开发者自定义的程序`a.c`:
```c
#include "span.h"
#define MLN_FUNC_FLAG
#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);
})
int main(void)
{
mln_span_start();
bcd(1, 2);
mln_span_stop();
mln_span_dump();
mln_span_release();
return 0;
}
```

编译程序:

```bash
cc -o a a.c span.c -I /usr/local/melon/include/ -L /usr/local/melon/lib/ -lmelon -ggdb
```

执行一下,可以看到如下输出:

```
| bcd at a.c:13 takes 1 (us)
| abc at a.c:9 takes 0 (us)
| abc at a.c:9 takes 0 (us)
```

Loading

0 comments on commit 22f0165

Please sign in to comment.