From 146096546716bf68c431f29e19c4e6d8e29c5923 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Fri, 20 Jul 2007 15:51:06 +0000 Subject: [PATCH] Memory reporting. git-svn-id: file:///svn/unbound/trunk@447 be551aaa-1e26-0410-a405-d3ace91eadb9 --- daemon/worker.c | 38 ++++++++++++++++++++++++++++++ doc/Changelog | 2 ++ services/listen_dnsport.c | 13 +++++++++++ services/listen_dnsport.h | 8 +++++++ services/mesh.c | 13 +++++++++++ services/mesh.h | 7 ++++++ services/outside_network.c | 48 ++++++++++++++++++++++++++++++++++++++ services/outside_network.h | 8 +++++++ testcode/fake_event.c | 15 ++++++++++++ util/alloc.c | 13 +++++++++++ util/alloc.h | 7 ++++++ util/netevent.c | 24 +++++++++++++++++++ util/netevent.h | 16 +++++++++++++ util/region-allocator.c | 11 +++++++++ util/region-allocator.h | 3 +++ util/storage/slabhash.c | 12 ++++++++++ util/storage/slabhash.h | 8 +++++++ 17 files changed, 246 insertions(+) diff --git a/daemon/worker.c b/daemon/worker.c index 32ad955bf..4043c4ff8 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -54,6 +54,7 @@ #include "services/outside_network.h" #include "services/outbound_list.h" #include "services/cache/rrset.h" +#include "services/cache/infra.h" #include "services/mesh.h" #include "util/data/msgparse.h" #include "util/data/msgencode.h" @@ -68,6 +69,34 @@ /** Size of an UDP datagram */ #define NORMAL_UDP_SIZE 512 /* bytes */ +/** Report on memory usage by this thread and global */ +static void +worker_mem_report(struct worker* worker) +{ + size_t total, front, back, mesh, msg, rrset, infra, ac, superac; + size_t me; + if(verbosity < VERB_ALGO) + return; + front = listen_get_mem(worker->front); + back = outnet_get_mem(worker->back); + msg = slabhash_get_mem(worker->env.msg_cache); + rrset = slabhash_get_mem(&worker->env.rrset_cache->table); + infra = slabhash_get_mem(worker->env.infra_cache->hosts); + mesh = mesh_get_mem(worker->env.mesh); + ac = alloc_get_mem(&worker->alloc); + superac = alloc_get_mem(&worker->daemon->superalloc); + me = sizeof(*worker) + sizeof(*worker->base) + sizeof(*worker->comsig) + + comm_point_get_mem(worker->cmd_com) + + sizeof(worker->rndstate) + region_get_mem(worker->scratchpad); + total = front+back+mesh+msg+rrset+infra+ac+superac+me; + log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u " + "rrset=%u infra=%u alloccache=%u globalalloccache=%u me=%u", + (unsigned)total, (unsigned)front, (unsigned)back, + (unsigned)mesh, (unsigned)msg, (unsigned)rrset, + (unsigned)infra, (unsigned)ac, (unsigned)superac, + (unsigned)me); +} + void worker_send_cmd(struct worker* worker, ldns_buffer* buffer, enum worker_commands cmd) @@ -95,6 +124,7 @@ worker_handle_reply(struct comm_point* c, void* arg, int error, if(error != 0) { mesh_report_reply(worker->env.mesh, &e, 0, reply_info); + worker_mem_report(worker); return 0; } /* sanity check. */ @@ -105,9 +135,11 @@ worker_handle_reply(struct comm_point* c, void* arg, int error, /* error becomes timeout for the module as if this reply * never arrived. */ mesh_report_reply(worker->env.mesh, &e, 0, reply_info); + worker_mem_report(worker); return 0; } mesh_report_reply(worker->env.mesh, &e, 1, reply_info); + worker_mem_report(worker); return 0; } @@ -122,6 +154,7 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error, verbose(VERB_ALGO, "worker scvd callback for qstate %p", e->qstate); if(error != 0) { mesh_report_reply(worker->env.mesh, e, 0, reply_info); + worker_mem_report(worker); return 0; } /* sanity check. */ @@ -133,9 +166,11 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error, * never arrived. */ verbose(VERB_ALGO, "worker: bad reply handled as timeout"); mesh_report_reply(worker->env.mesh, e, 0, reply_info); + worker_mem_report(worker); return 0; } mesh_report_reply(worker->env.mesh, e, 1, reply_info); + worker_mem_report(worker); return 0; } @@ -507,6 +542,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, /* the max request number has been reached, stop accepting */ listen_pushback(worker->front); } + worker_mem_report(worker); return 0; } @@ -680,6 +716,7 @@ worker_init(struct worker* worker, struct config_file *cfg, worker_delete(worker); return 0; } + worker_mem_report(worker); return 1; } @@ -696,6 +733,7 @@ worker_delete(struct worker* worker) return; mesh_stats(worker->env.mesh, "mesh has"); server_stats_log(&worker->stats, worker->thread_num); + worker_mem_report(worker); mesh_delete(worker->env.mesh); listen_delete(worker->front); outside_network_delete(worker->back); diff --git a/doc/Changelog b/doc/Changelog index b89ac23ed..500c6e73b 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -10,6 +10,8 @@ - TODO items from forgery-resilience draft. and on memory handling improvements. - renamed module_event_timeout to module_event_noreply. + - memory reporting code; reports on memory usage after handling + a network packet (not on cache replies). 19 July 2007: Wouter - shuffle NS selection when getting nameserver target addresses. diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index c996e16d3..125685d15 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -452,3 +452,16 @@ void listening_ports_free(struct listen_port* list) list = nx; } } + +size_t listen_get_mem(struct listen_dnsport* listen) +{ + size_t s = sizeof(*listen) + sizeof(*listen->base) + + sizeof(*listen->udp_buff) + + ldns_buffer_capacity(listen->udp_buff); + struct listen_list* p; + for(p = listen->cps; p; p = p->next) { + s += sizeof(*p); + s += comm_point_get_mem(p->com); + } + return s; +} diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index b8e0f16e4..4fabea50b 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -141,9 +141,17 @@ void listen_resume(struct listen_dnsport* listen); /** * delete the listening structure + * @param listen: listening structure. */ void listen_delete(struct listen_dnsport* listen); +/** + * get memory size used by the listening structs + * @param listen: listening structure. + * @return: size in bytes. + */ +size_t listen_get_mem(struct listen_dnsport* listen); + /** * Create and bind nonblocking UDP socket * @param addr: address info ready to make socket. diff --git a/services/mesh.c b/services/mesh.c index 27c1e5125..0061c1e1d 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -575,3 +575,16 @@ mesh_stats(struct mesh_area* mesh, const char* str) timehist_log(mesh->histogram); } } + +size_t +mesh_get_mem(struct mesh_area* mesh) +{ + struct mesh_state* m; + size_t s = sizeof(*mesh) + sizeof(struct timehist) + + sizeof(struct th_buck)*mesh->histogram->num; + RBTREE_FOR(m, struct mesh_state*, &mesh->all) { + /* all, including m itself allocated in qstate region */ + s += region_get_mem(m->s.region); + } + return s; +} diff --git a/services/mesh.h b/services/mesh.h index bf6a863e0..75afdcb70 100644 --- a/services/mesh.h +++ b/services/mesh.h @@ -350,4 +350,11 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate, */ void mesh_stats(struct mesh_area* mesh, const char* str); +/** + * Calculate memory size in use by mesh and all queries inside it. + * @param mesh: the mesh to examine. + * @return size in bytes. + */ +size_t mesh_get_mem(struct mesh_area* mesh); + #endif /* SERVICES_MESH_H */ diff --git a/services/outside_network.c b/services/outside_network.c index facc87cd7..da0aec649 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1200,3 +1200,51 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg) serviced_delete(sq); } } + +/** get memory used by waiting tcp entry (in use or not) */ +static size_t +waiting_tcp_get_mem(struct waiting_tcp* w) +{ + size_t s; + if(!w) return 0; + s = sizeof(*w) + w->pkt_len; + if(w->timer) + s += comm_timer_get_mem(w->timer); + return s; +} + +size_t outnet_get_mem(struct outside_network* outnet) +{ + size_t i; + struct waiting_tcp* w; + struct serviced_query* sq; + struct service_callback* sb; + size_t s = sizeof(*outnet) + sizeof(*outnet->base) + + sizeof(*outnet->udp_buff) + + ldns_buffer_capacity(outnet->udp_buff); + /* second buffer is not ours */ + s += sizeof(struct comm_point*)*outnet->num_udp4; + for(i=0; inum_udp4; i++) + s += comm_point_get_mem(outnet->udp4_ports[i]); + s += sizeof(struct comm_point*)*outnet->num_udp6; + for(i=0; inum_udp6; i++) + s += comm_point_get_mem(outnet->udp6_ports[i]); + s += sizeof(struct pending_tcp*)*outnet->num_tcp; + for(i=0; inum_tcp; i++) { + s += sizeof(struct pending_tcp); + s += comm_point_get_mem(outnet->tcp_conns[i]->c); + if(outnet->tcp_conns[i]->query) + s += waiting_tcp_get_mem(outnet->tcp_conns[i]->query); + } + for(w=outnet->tcp_wait_first; w; w = w->next_waiting) + s += waiting_tcp_get_mem(w); + s += sizeof(*outnet->pending); + s += sizeof(struct pending) * outnet->pending->count; + s += sizeof(*outnet->serviced); + RBTREE_FOR(sq, struct serviced_query*, outnet->serviced) { + s += sizeof(*sq) + sq->qbuflen; + for(sb = sq->cblist; sb; sb = sb->next) + s += sizeof(*sb); + } + return s; +} diff --git a/services/outside_network.h b/services/outside_network.h index 0e7e59c33..8765c93e8 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -363,4 +363,12 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, */ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg); +/** + * Get memory size in use by outside network. + * Counts buffers and outstanding query (serviced queries) malloced data. + * @param outnet: outside network structure. + * @return size in bytes. + */ +size_t outnet_get_mem(struct outside_network* outnet); + #endif /* OUTSIDE_NETWORK_H */ diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 88e6b94d8..83c477edf 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -901,4 +901,19 @@ void comm_point_delete(struct comm_point* c) free(c); } +size_t listen_get_mem(struct listen_dnsport* ATTR_UNUSED(listen)) +{ + return 0; +} + +size_t outnet_get_mem(struct outside_network* ATTR_UNUSED(outnet)) +{ + return 0; +} + +size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c)) +{ + return 0; +} + /*********** End of Dummy routines ***********/ diff --git a/util/alloc.c b/util/alloc.c index cdebd3c52..a652706fb 100644 --- a/util/alloc.c +++ b/util/alloc.c @@ -234,3 +234,16 @@ alloc_stats(struct alloc_cache* alloc) log_info("%salloc: %d in cache.", alloc->super?"":"sup", (int)alloc->num_quar); } + +size_t alloc_get_mem(struct alloc_cache* alloc) +{ + size_t s = sizeof(*alloc); + if(!alloc->super) { + lock_quick_lock(&alloc->lock); /* superalloc needs locking */ + } + s += sizeof(alloc_special_t) * alloc->num_quar; + if(!alloc->super) { + lock_quick_unlock(&alloc->lock); + } + return s; +} diff --git a/util/alloc.h b/util/alloc.h index 9a0115608..761213e8b 100644 --- a/util/alloc.h +++ b/util/alloc.h @@ -119,6 +119,13 @@ alloc_special_t* alloc_special_obtain(struct alloc_cache* alloc); */ void alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem); +/** + * Get memory size of alloc cache, alloc structure including special types. + * @param alloc: on what alloc. + * @return size in bytes. + */ +size_t alloc_get_mem(struct alloc_cache* alloc); + /** * Print debug information (statistics). * @param alloc: on what alloc. diff --git a/util/netevent.c b/util/netevent.c index 41adeaadd..363a50144 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -984,6 +984,24 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec) } } +size_t comm_point_get_mem(struct comm_point* c) +{ + size_t s; + if(!c) + return 0; + s = sizeof(*c) + sizeof(*c->ev); + if(c->timeout) + s += sizeof(*c->timeout); + if(c->type == comm_tcp || c->type == comm_local) + s += sizeof(*c->buffer) + ldns_buffer_capacity(c->buffer); + if(c->type == comm_tcp_accept) { + int i; + for(i=0; imax_tcp_count; i++) + s += comm_point_get_mem(c->tcp_handlers[i]); + } + return s; +} + struct comm_timer* comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg) { @@ -1055,6 +1073,12 @@ comm_timer_is_set(struct comm_timer* timer) return (int)timer->ev_timer->enabled; } +size_t +comm_timer_get_mem(struct comm_timer* timer) +{ + return sizeof(*timer) + sizeof(struct internal_timer); +} + struct comm_signal* comm_signal_create(struct comm_base* base, void (*callback)(int, void*), void* cb_arg) diff --git a/util/netevent.h b/util/netevent.h index 460bc0134..a1bb56bbb 100644 --- a/util/netevent.h +++ b/util/netevent.h @@ -384,6 +384,15 @@ void comm_point_stop_listening(struct comm_point* c); */ void comm_point_start_listening(struct comm_point* c, int newfd, int sec); +/** + * Get size of memory used by comm point. + * For TCP handlers this includes subhandlers. + * For UDP handlers, this does not include the (shared) UDP buffer. + * @param c: commpoint. + * @return size in bytes. + */ +size_t comm_point_get_mem(struct comm_point* c); + /** * create timer. Not active upon creation. * @param base: event handling base. @@ -420,6 +429,13 @@ void comm_timer_delete(struct comm_timer* timer); */ int comm_timer_is_set(struct comm_timer* timer); +/** + * Get size of memory used by comm timer. + * @param timer: the timer to examine. + * @return size in bytes. + */ +size_t comm_timer_get_mem(struct comm_timer* timer); + /** * Create a signal handler. Call signal_bind() later to bind to a signal. * @param base: communication base to use. diff --git a/util/region-allocator.c b/util/region-allocator.c index daa1c0a89..b3946edf4 100644 --- a/util/region-allocator.c +++ b/util/region-allocator.c @@ -508,3 +508,14 @@ region_log_stats(region_type *region) } log_info("memory: %s", buf); } + +size_t +region_get_mem(region_type* region) +{ + size_t s = sizeof(*region); + s += region->total_allocated + region->chunk_size - region->allocated; + s += region->maximum_cleanup_count * sizeof(cleanup_type); + if(region->recycle_bin) + s += sizeof(struct recycle_elem*)*region->large_object_size; + return s; +} diff --git a/util/region-allocator.h b/util/region-allocator.h index 3c857cb0c..c10897d9c 100644 --- a/util/region-allocator.h +++ b/util/region-allocator.h @@ -173,4 +173,7 @@ size_t region_get_recycle_size(region_type* region); /** Debug print REGION statistics to LOG */ void region_log_stats(region_type *region); +/** get total memory size in use by region */ +size_t region_get_mem(region_type* region); + #endif /* _REGION_ALLOCATOR_H_ */ diff --git a/util/storage/slabhash.c b/util/storage/slabhash.c index 61393c1e1..2ce58f7cc 100644 --- a/util/storage/slabhash.c +++ b/util/storage/slabhash.c @@ -144,6 +144,18 @@ size_t slabhash_get_size(struct slabhash* sl) return total; } +size_t slabhash_get_mem(struct slabhash* sl) +{ + size_t i, total = sizeof(*sl); + for(i=0; isize; i++) { + lock_quick_lock(&sl->array[i]->lock); + total += sizeof(struct lruhash) + sl->array[i]->space_used + + sizeof(struct lruhash_bin)*sl->array[i]->size; + lock_quick_unlock(&sl->array[i]->lock); + } + return total; +} + struct lruhash* slabhash_gettable(struct slabhash* sl, hashvalue_t hash) { return sl->array[slab_idx(sl, hash)]; diff --git a/util/storage/slabhash.h b/util/storage/slabhash.h index d530d7a1e..be7fd07d4 100644 --- a/util/storage/slabhash.h +++ b/util/storage/slabhash.h @@ -142,9 +142,17 @@ void slabhash_status(struct slabhash* table, const char* id, int extended); /** * Retrieve slab hash total size. * @param table: hash table. + * @return size configured as max. */ size_t slabhash_get_size(struct slabhash* table); +/** + * Retrieve slab hash current memory use. + * @param table: hash table. + * @return memory in use. + */ +size_t slabhash_get_mem(struct slabhash* table); + /** * Get lruhash table for a given hash value * @param table: slabbed hash table. -- 2.47.2