From 9b8c35fb258bd6f99372be7f1f3eb725b0298aea Mon Sep 17 00:00:00 2001 From: hexian000 Date: Fri, 1 Sep 2023 13:39:52 +0800 Subject: [PATCH] ruleset: count heap objects Signed-off-by: hexian000 --- src/http_api.c | 31 ++++++++++++++++++++++++------- src/ruleset.c | 38 +++++++++++++++++++++++++++++--------- src/ruleset.h | 7 ++++++- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/http_api.c b/src/http_api.c index b1a0c53..b7d1c0d 100644 --- a/src/http_api.c +++ b/src/http_api.c @@ -1,11 +1,13 @@ #include "http_impl.h" #include "net/url.h" #include "utils/formats.h" +#include "utils/posixtime.h" #include "utils/slog.h" #include "resolver.h" #include "ruleset.h" #include +#include #define FORMAT_BYTES(name, value) \ char name[16]; \ @@ -57,12 +59,15 @@ static void server_stats( avgresolv_hrs, xfer_up, xfer_down, avgbw_up, avgbw_down); if (G.ruleset != NULL) { - const size_t heap_bytes = ruleset_memused(G.ruleset); + struct ruleset_memstats mem; + ruleset_memstats(G.ruleset, &mem); char heap_total[16]; (void)format_iec_bytes( - heap_total, sizeof(heap_total), (double)heap_bytes); + heap_total, sizeof(heap_total), + (double)mem.byt_allocated); BUF_APPENDF( - ctx->wbuf, "Ruleset Memory : %s\n", heap_total); + ctx->wbuf, "Ruleset Memory : %s (%zu objects)\n", + heap_total, mem.num_object); } } @@ -247,12 +252,24 @@ static void http_handle_ruleset( if (!http_leafnode_check(ctx, uri, "POST", false)) { return; } + const int64_t start = clock_monotonic(); ruleset_gc(ruleset); - const size_t livemem = ruleset_memused(ruleset); - char buf[16]; - (void)format_iec_bytes(buf, sizeof(buf), (double)livemem); + struct ruleset_memstats mem; + ruleset_memstats(ruleset, &mem); + char livemem[16]; + (void)format_iec_bytes( + livemem, sizeof(livemem), (double)mem.byt_allocated); + char timecost[16]; + (void)format_duration( + timecost, sizeof(timecost), + make_duration_nanos(clock_monotonic() - start)); RESPHDR_POST(ctx->wbuf, HTTP_OK); - BUF_APPENDF(ctx->wbuf, "Ruleset Live Memory: %s\n", buf); + BUF_APPENDF( + ctx->wbuf, + "Num Live Object : %zu\n" + "Ruleset Live Memory : %s\n" + "Time Cost : %s\n", + mem.num_object, livemem, timecost); return; } diff --git a/src/ruleset.c b/src/ruleset.c index b7a17a2..42494c9 100644 --- a/src/ruleset.c +++ b/src/ruleset.c @@ -29,9 +29,9 @@ #include struct ruleset { - lua_State *L; - size_t alloc_size; struct ev_loop *loop; + struct ruleset_memstats heap; + lua_State *L; struct ev_timer ticker; }; @@ -106,7 +106,7 @@ static int ruleset_traceback(lua_State *restrict L) static void check_memlimit(const struct ruleset *restrict r) { const size_t memlimit = G.conf->memlimit; - if (memlimit == 0 || (r->alloc_size >> 20u) < memlimit) { + if (memlimit == 0 || (r->heap.byt_allocated >> 20u) < memlimit) { return; } lua_gc(r->L, LUA_GCCOLLECT, 0); @@ -406,12 +406,30 @@ static int ruleset_luainit_(lua_State *restrict L) static void *l_alloc(void *ud, void *ptr, size_t osize, size_t nsize) { struct ruleset *restrict r = ud; - r->alloc_size = r->alloc_size + nsize - osize; if (nsize == 0) { + /* free */ free(ptr); + if (ptr != NULL) { + r->heap.byt_allocated -= osize; + r->heap.num_object--; + } return NULL; } - return realloc(ptr, nsize); + if (ptr == NULL) { + /* malloc */ + void *ret = malloc(nsize); + if (ret != NULL) { + r->heap.num_object++; + r->heap.byt_allocated += nsize; + } + return ret; + } + /* realloc */ + void *ret = realloc(ptr, nsize); + if (ret != NULL) { + r->heap.byt_allocated = r->heap.byt_allocated - osize + nsize; + } + return ret; } static int l_panic(lua_State *L) @@ -430,14 +448,15 @@ struct ruleset *ruleset_new(struct ev_loop *loop) if (r == NULL) { return NULL; } + r->loop = loop; + r->heap = (struct ruleset_memstats){ 0 }; lua_State *restrict L = lua_newstate(l_alloc, r); if (L == NULL) { ruleset_free(r); return NULL; } - lua_atpanic(L, l_panic); + (void)lua_atpanic(L, l_panic); r->L = L; - r->loop = loop; { /* initialize in advance to prevent undefined behavior */ struct ev_timer *restrict w_timer = &r->ticker; @@ -636,9 +655,10 @@ struct dialreq *ruleset_route6(struct ruleset *r, const char *request) return dispatch_req(r, "route6", request); } -size_t ruleset_memused(const struct ruleset *restrict r) +void ruleset_memstats( + const struct ruleset *restrict r, struct ruleset_memstats *restrict s) { - return r->alloc_size; + *s = r->heap; } static int ruleset_stats_(lua_State *restrict L) diff --git a/src/ruleset.h b/src/ruleset.h index 430a029..26ccf34 100644 --- a/src/ruleset.h +++ b/src/ruleset.h @@ -9,6 +9,11 @@ struct ev_loop; struct ruleset; +struct ruleset_memstats { + size_t num_object; + size_t byt_allocated; +}; + struct ruleset *ruleset_new(struct ev_loop *loop); const char *ruleset_invoke(struct ruleset *r, const char *code, size_t len); const char *ruleset_load(struct ruleset *r, const char *code, size_t len); @@ -20,7 +25,7 @@ struct dialreq *ruleset_resolve(struct ruleset *r, const char *request); struct dialreq *ruleset_route(struct ruleset *r, const char *request); struct dialreq *ruleset_route6(struct ruleset *r, const char *request); -size_t ruleset_memused(const struct ruleset *r); +void ruleset_memstats(const struct ruleset *r, struct ruleset_memstats *s); const char *ruleset_stats(struct ruleset *r, double dt); #endif /* RULESET_H */