From acb60628f53ba1fc29d1a554683acdb03f961c6f Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Wed, 2 Jun 2010 22:20:40 +0200 Subject: Implements command that shows memory usage. --- doc/reply_codes | 1 + lib/event.c | 1 + lib/mempool.c | 22 +++++++++++++++++++++- lib/resource.c | 38 ++++++++++++++++++++++++++++++++++++-- lib/resource.h | 5 +++++ lib/slab.c | 38 ++++++++++++++++++++++++++++++++++++-- nest/cmds.c | 30 ++++++++++++++++++++++++++++++ nest/cmds.h | 1 + nest/config.Y | 5 ++++- nest/proto.c | 2 +- nest/rt-attr.c | 3 ++- nest/rt-table.c | 3 ++- sysdep/unix/io.c | 3 +++ 13 files changed, 143 insertions(+), 9 deletions(-) diff --git a/doc/reply_codes b/doc/reply_codes index 22e0fd2..a0db2ca 100644 --- a/doc/reply_codes +++ b/doc/reply_codes @@ -44,6 +44,7 @@ Reply codes of BIRD command-line interface 1015 Show ospf interface 1016 Show ospf state/topology 1017 Show ospf lsadb +1018 Show memory 8000 Reply too long 8001 Route not found diff --git a/lib/event.c b/lib/event.c index ce5e81c..916cf55 100644 --- a/lib/event.c +++ b/lib/event.c @@ -50,6 +50,7 @@ static struct resclass ev_class = { sizeof(event), (void (*)(resource *)) ev_postpone, ev_dump, + NULL, NULL }; diff --git a/lib/mempool.c b/lib/mempool.c index 0cb06b5..65072f9 100644 --- a/lib/mempool.c +++ b/lib/mempool.c @@ -43,13 +43,15 @@ struct linpool { static void lp_free(resource *); static void lp_dump(resource *); static resource *lp_lookup(resource *, unsigned long); +static size_t lp_memsize(resource *r); static struct resclass lp_class = { "LinPool", sizeof(struct linpool), lp_free, lp_dump, - lp_lookup + lp_lookup, + lp_memsize }; /** @@ -235,6 +237,24 @@ lp_dump(resource *r) m->total_large); } +static size_t +lp_memsize(resource *r) +{ + linpool *m = (linpool *) r; + struct lp_chunk *c; + int cnt = 0; + + for(c=m->first; c; c=c->next) + cnt++; + for(c=m->first_large; c; c=c->next) + cnt++; + + return ALLOC_OVERHEAD + sizeof(struct linpool) + + cnt * (ALLOC_OVERHEAD + sizeof(sizeof(struct lp_chunk))) + + m->total + m->total_large; +} + + static resource * lp_lookup(resource *r, unsigned long a) { diff --git a/lib/resource.c b/lib/resource.c index 5ba23f1..24164ec 100644 --- a/lib/resource.c +++ b/lib/resource.c @@ -37,13 +37,15 @@ struct pool { static void pool_dump(resource *); static void pool_free(resource *); static resource *pool_lookup(resource *, unsigned long); +static size_t pool_memsize(resource *P); static struct resclass pool_class = { "Pool", sizeof(pool), pool_free, pool_dump, - pool_lookup + pool_lookup, + pool_memsize }; pool root_pool; @@ -95,6 +97,19 @@ pool_dump(resource *P) indent -= 3; } +static size_t +pool_memsize(resource *P) +{ + pool *p = (pool *) P; + resource *r; + size_t sum = sizeof(pool) + ALLOC_OVERHEAD; + + WALK_LIST(r, p->inside) + sum += rmemsize(r); + + return sum; +} + static resource * pool_lookup(resource *P, unsigned long a) { @@ -177,6 +192,17 @@ rdump(void *res) debug("NULL\n"); } +size_t +rmemsize(void *res) +{ + resource *r = res; + if (!r) + return 0; + if (!r->class->memsize) + return r->class->size + ALLOC_OVERHEAD; + return r->class->memsize(r); +} + /** * ralloc - create a resource * @p: pool to create the resource in @@ -277,12 +303,20 @@ mbl_lookup(resource *r, unsigned long a) return NULL; } +static size_t +mbl_memsize(resource *r) +{ + struct mblock *m = (struct mblock *) r; + return ALLOC_OVERHEAD + sizeof(struct mblock) + m->size; +} + static struct resclass mb_class = { "Memory", 0, mbl_free, mbl_debug, - mbl_lookup + mbl_lookup, + mbl_memsize }; /** diff --git a/lib/resource.h b/lib/resource.h index 8dd441f..5cb5e27 100644 --- a/lib/resource.h +++ b/lib/resource.h @@ -26,8 +26,12 @@ struct resclass { void (*free)(resource *); /* Freeing function */ void (*dump)(resource *); /* Dump to debug output */ resource *(*lookup)(resource *, unsigned long); /* Look up address (only for debugging) */ + size_t (*memsize)(resource *); /* Return size of memory used by the resource, may be NULL */ }; +/* Estimate of system allocator overhead per item, for memory consumtion stats */ +#define ALLOC_OVERHEAD 8 + /* Generic resource manipulation */ typedef struct pool pool; @@ -36,6 +40,7 @@ void resource_init(void); pool *rp_new(pool *, char *); /* Create new pool */ void rfree(void *); /* Free single resource */ void rdump(void *); /* Dump to debug output */ +size_t rmemsize(void *res); /* Return size of memory used by the resource */ void rlookup(unsigned long); /* Look up address (only for debugging) */ void rmove(void *, pool *); /* Move to a different pool */ diff --git a/lib/slab.c b/lib/slab.c index 8cce52f..af6b50b 100644 --- a/lib/slab.c +++ b/lib/slab.c @@ -41,6 +41,7 @@ static void slab_free(resource *r); static void slab_dump(resource *r); static resource *slab_lookup(resource *r, unsigned long addr); +static size_t slab_memsize(resource *r); #ifdef FAKE_SLAB @@ -58,7 +59,8 @@ static struct resclass sl_class = { "FakeSlab", sizeof(struct slab), slab_free, - slab_dump + slab_dump, + slab_memsize }; struct sl_obj { @@ -116,6 +118,20 @@ slab_dump(resource *r) debug("(%d objects per %d bytes)\n", cnt, s->size); } +static size_t +slab_memsize(resource *r) +{ + slab *s = (slab *) r; + int cnt = 0; + struct sl_obj *o; + + WALK_LIST(o, s->objs) + cnt++; + + return ALLOC_OVERHEAD + sizeof(struct slab) + cnt * (ALLOC_OVERHEAD + s->size); +} + + #else /* @@ -136,7 +152,8 @@ static struct resclass sl_class = { sizeof(struct slab), slab_free, slab_dump, - slab_lookup + slab_lookup, + slab_memsize }; struct sl_head { @@ -324,6 +341,23 @@ slab_dump(resource *r) debug("(%de+%dp+%df blocks per %d objs per %d bytes)\n", ec, pc, fc, s->objs_per_slab, s->obj_size); } +static size_t +slab_memsize(resource *r) +{ + slab *s = (slab *) r; + int heads = 0; + struct sl_head *h; + + WALK_LIST(h, s->empty_heads) + heads++; + WALK_LIST(h, s->partial_heads) + heads++; + WALK_LIST(h, s->full_heads) + heads++; + + return ALLOC_OVERHEAD + sizeof(struct slab) + heads * (ALLOC_OVERHEAD + SLAB_SIZE); +} + static resource * slab_lookup(resource *r, unsigned long a) { diff --git a/nest/cmds.c b/nest/cmds.c index 16fbba6..8ac3209 100644 --- a/nest/cmds.c +++ b/nest/cmds.c @@ -11,6 +11,7 @@ #include "conf/conf.h" #include "nest/cmds.h" #include "lib/string.h" +#include "lib/resource.h" void cmd_show_status(void) @@ -47,3 +48,32 @@ cmd_show_symbols(struct symbol *sym) cli_msg(0, ""); } } + +static void +print_size(char *dsc, size_t val) +{ + char *px = " kMG"; + int i = 0; + while ((val >= 10000) && (i < 3)) + { + val = (val + 512) / 1024; + i++; + } + + cli_msg(-1018, "%-17s %4u %cB", dsc, (unsigned) val, px[i]); +} + +extern pool *rt_table_pool; +extern pool *rta_pool; +extern pool *proto_pool; + +void +cmd_show_memory(void) +{ + cli_msg(-1018, "BIRD memory usage"); + print_size("Routing tables:", rmemsize(rt_table_pool)); + print_size("Route attributes:", rmemsize(rta_pool)); + print_size("Protocols:", rmemsize(proto_pool)); + print_size("Total:", rmemsize(&root_pool)); + cli_msg(0, ""); +} diff --git a/nest/cmds.h b/nest/cmds.h index ae1c9e2..3b86a92 100644 --- a/nest/cmds.h +++ b/nest/cmds.h @@ -8,3 +8,4 @@ void cmd_show_status(void); void cmd_show_symbols(struct symbol *sym); +void cmd_show_memory(void); diff --git a/nest/config.Y b/nest/config.Y index 7bb0525..a8e6bf8 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -45,7 +45,7 @@ CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILT CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE) CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION) -CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT) +CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY) CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE) @@ -324,6 +324,9 @@ CF_CLI_HELP(SHOW, ..., [[Show status information]]) CF_CLI(SHOW STATUS,,, [[Show router status]]) { cmd_show_status(); } ; +CF_CLI(SHOW MEMORY,,, [[Show memory usage]]) +{ cmd_show_memory(); } ; + CF_CLI(SHOW PROTOCOLS, proto_patt2, [ | \"\"], [[Show routing protocols]]) { proto_apply_cmd($3, proto_cmd_show, 0, 0); } ; diff --git a/nest/proto.c b/nest/proto.c index 46147a4..c9e2f5c 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -20,7 +20,7 @@ #include "nest/cli.h" #include "filter/filter.h" -static pool *proto_pool; +pool *proto_pool; static list protocol_list; static list proto_list; diff --git a/nest/rt-attr.c b/nest/rt-attr.c index b553475..abd49c7 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -54,8 +54,9 @@ #include "lib/resource.h" #include "lib/string.h" +pool *rta_pool; + static slab *rta_slab; -static pool *rta_pool; struct protocol *attr_class_to_protocol[EAP_MAX]; diff --git a/nest/rt-table.c b/nest/rt-table.c index 8736574..8cca42a 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -43,10 +43,11 @@ #include "lib/string.h" #include "lib/alloca.h" +pool *rt_table_pool; + static slab *rte_slab; static linpool *rte_update_pool; -static pool *rt_table_pool; static list routing_tables; static void rt_format_via(rte *e, byte *via); diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 8058fa6..690c8fc 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -76,6 +76,7 @@ static struct resclass rf_class = { sizeof(struct rfile), rf_free, rf_dump, + NULL, NULL }; @@ -203,6 +204,7 @@ static struct resclass tm_class = { sizeof(timer), tm_free, tm_dump, + NULL, NULL }; @@ -573,6 +575,7 @@ static struct resclass sk_class = { sizeof(sock), sk_free, sk_dump, + NULL, NULL }; -- cgit v1.2.3