--------------------- PatchSet 2192 Date: 2001/05/02 20:21:59 Author: akroonmaa Branch: chunked_mempools Tag: (none) Log: Move most stuff out from MemPoolStats.c to lib/MemPools.c rewrite stats reporting stuff further reduce API namespace Members: include/MemPool.h:1.1.2.11->1.1.2.12 lib/MemPool.c:1.1.2.13->1.1.2.14 src/MemPoolStats.c:1.1.2.16->1.1.2.17 src/protos.h:1.23.4.6->1.23.4.7 Index: squid/include/MemPool.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/Attic/MemPool.h,v retrieving revision 1.1.2.11 retrieving revision 1.1.2.12 diff -u -r1.1.2.11 -r1.1.2.12 --- squid/include/MemPool.h 1 May 2001 00:02:31 -0000 1.1.2.11 +++ squid/include/MemPool.h 2 May 2001 20:21:59 -0000 1.1.2.12 @@ -19,12 +19,29 @@ #define MEM_MIN_FREE 32 #define MEM_MAX_FREE 65535 /* ushort is max number of items per chunk */ +enum { + MPOOL_INIT, + MPOOL_TUNE_CHUNKSIZE, + MPOOL_FLUSH_METERS, + MPOOL_CLEAN_POOL, + MPOOL_GET_INUSE, + MPOOL_SYNC_HWATER, + MPOOL_DESTROY, + MPOOL_GET_IDLE_LIMIT, + MPOOL_SET_IDLE_LIMIT, + MPOOL_GET_TOTAL, + MPOOL_GET_THEMETER, + MPOOL_GET_STATS, + MPOOL_CLEAN_MODULE, + MPOOL_GET_OVERHEAD +}; + typedef struct _MemPoolMeter MemPoolMeter; typedef struct _MemPool MemPool; typedef struct _MemMeter MemMeter; typedef struct _MemChunk MemChunk; +typedef struct _MemPoolStats MemPoolStats; -extern void memArrayInit(Array * s); /* object to track per-action memory usage (e.g. #idle objects) */ struct _MemMeter { @@ -53,7 +70,7 @@ const char *label; size_t obj_size; size_t chunk_size; - int capacity; + int chunk_capacity; int memPID; int chunkCount; size_t alloc_calls; @@ -76,29 +93,60 @@ time_t lastref; }; +struct _MemPoolStats { + MemPool *pool; + const char *label; + MemPoolMeter *meter; + int obj_size; + int chunk_capacity; + int chunk_size; + int chunks_alloc; + int chunks_inuse; + int chunks_partial; + int chunks_free; + int items_alloc; + int items_inuse; + int items_idle; + int overhead; +}; + #define SIZEOF_CHUNK ( ( sizeof(MemChunk) + sizeof(double) -1) / sizeof(double) ) * sizeof(double); extern unsigned int mem_pool_alloc_calls; extern unsigned int mem_pool_free_calls; +/* memPools */ + extern void memConfigure(void); extern void memInitModule(void); -/* memPools */ -extern void memPoolTune(MemPool * pool, size_t chunksize, int unused); +extern int memPoolControl(void ** pool, int cmd, size_t value); extern MemPool *memPoolCreate(const char *label, size_t obj_size); -extern void memPoolDestroy(MemPool * pool); extern void *memPoolAlloc(MemPool * pool); extern void memPoolFree(MemPool * pool, void *obj); -extern int memPoolInUseCount(const MemPool * pool); -extern void memPoolClean(MemPool * pool, time_t maxage); extern void memPoolCleanIdlePools(void *unused); -extern void memPoolFlushMeters(MemPool * pool); -extern size_t memPoolsTotalAllocated(void); + +#if !MPOOL_INTERNAL +#define memPoolTune(pool, size, un) ( memPoolControl((void *) (pool), MPOOL_TUNE_CHUNKSIZE, (size)) ) +#define memPoolInUseCount(pool) ( memPoolControl((void *) (pool), MPOOL_GET_INUSE, 0) ) +#define memPoolFlushMeters(pool) ( memPoolControl((void *) (pool), MPOOL_FLUSH_METERS, 0) ) +#define memPoolDestroy(pool) ( memPoolControl((void *) (pool), MPOOL_DESTROY, 0) ) +#define memPoolClean(pool, maxage) ( memPoolControl((void *) (pool), MPOOL_CLEAN_POOL, (maxage)) ) +#define memPoolCleanModule() ( memPoolControl(0, MPOOL_CLEAN_MODULE, 0) ) +#define memPoolInit() ( memPoolControl(0, MPOOL_INIT, 0) ) +#define memPoolIdleLimit() ( memPoolControl(0, MPOOL_GET_IDLE_LIMIT, 0) ) +#define memPoolSetIdleLimit(limit) ( memPoolControl(0, MPOOL_SET_IDLE_LIMIT, (limit)) ) +#define memPoolsTotalAllocated() ( memPoolControl(0, MPOOL_GET_TOTAL, 0) ) +#define memPoolGetOverhead() ( memPoolControl(0, MPOOL_GET_OVERHEAD, 0) ) +#define memPoolGetStats(stats, i) ( memPoolControl((void *) (stats), MPOOL_GET_STATS, (i)) ) +#define memPoolGetTheMeter(meter) ( memPoolControl((void *) (meter), MPOOL_GET_THEMETER, 0) ) + +#define memMeterSyncHWater(meter) ( memPoolControl((void *) (meter), MPOOL_SYNC_HWATER, 0) ) +#endif + /* MemMeter */ -extern void memMeterSyncHWater(MemMeter * m); #define memMeterCheckHWater(m) { if ((m).hwater_level < (m).level) memMeterSyncHWater(&(m)); } #define memMeterInc(m) { (m).level++; memMeterCheckHWater(m); } #define memMeterDec(m) { (m).level--; } Index: squid/lib/MemPool.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/Attic/MemPool.c,v retrieving revision 1.1.2.13 retrieving revision 1.1.2.14 diff -u -r1.1.2.13 -r1.1.2.14 --- squid/lib/MemPool.c 1 May 2001 00:05:29 -0000 1.1.2.13 +++ squid/lib/MemPool.c 2 May 2001 20:21:59 -0000 1.1.2.14 @@ -81,7 +81,7 @@ */ #define FLUSH_LIMIT 1000 /* Flush memPool counters to memMeters after flush limit calls */ - +#define MPOOL_INTERNAL 1 #include #include @@ -98,22 +98,47 @@ unsigned int mem_pool_alloc_calls = 0; unsigned int mem_pool_free_calls = 0; +int memPoolControl(void **pool, int cmd, size_t value); +MemPool *memPoolCreate(const char *label, size_t obj_size); +void *memPoolAlloc(MemPool * pool); +void memPoolFree(MemPool * pool, void *obj); + /* locals */ +static MemPoolMeter TheMeter; +static size_t mem_idle_limit = 0; -static Array *PoolArray = NULL; +static Array PoolArray; static int Pool_id_counter = 0; static int bounds; +static MemPool *lastPool; -static void memArrayGrow(Array * a, int min_capacity); -static void memArrayAppend(Array * s, void *obj); +static int memPoolCleanModule(void); +static void memMeterSyncHWater(MemMeter * m); +static int memCompChunks(MemChunk * chunkA, MemChunk * chunkB); +static int memCompObjChunks(void *obj, MemChunk * chunk); +static MemChunk *memPoolChunkNew(MemPool * pool); +static void memPoolChunkDestroy(MemPool * pool, MemChunk * chunk); +static void memPoolPush(MemPool * pool, void *obj); +static void *memPoolGet(MemPool * pool); +static void memPoolCreateChunk(MemPool * pool); +static void memPoolTune(MemPool * pool, size_t chunksize, int unused); +static void memPoolDestroy(MemPool * pool); +static void memPoolFlushMeters(MemPool * pool); +static void memPoolCleanOne(MemPool * pool, time_t maxage); +static void memPoolClean(MemPool * onePool, time_t maxage); +static void memPoolFlushMetersAll(MemPool * onePool); +static int memPoolInUseCount(const MemPool * pool); +static int memPoolGetStats(MemPoolStats * mp_st, int index); + +static void memArrayInit(Array * a); #if UNUSED_CODE static void memArrayClean(Array * s); static void memArrayDestroy(Array * s); #endif -static void memPoolCreateChunk(MemPool * pool); -static MemPool *lastPool; +static void memArrayAppend(Array * s, void *obj); +static void memArrayGrow(Array * a, int min_capacity); -void +static void memMeterSyncHWater(MemMeter * m) { assert(m); @@ -151,16 +176,16 @@ chunk->objCache = xcalloc(1, pool->chunk_size); Free = chunk->freeList = chunk->objCache; - for (i = 1; i < pool->capacity; i++) { + for (i = 1; i < pool->chunk_capacity; i++) { *Free = (void *) Free + pool->obj_size; Free = *Free; } chunk->nextFreeChunk = pool->nextFreeChunk; pool->nextFreeChunk = chunk; - memMeterAdd(pool->meter.alloc, pool->capacity); - memMeterAdd(pool->meter.idle, pool->capacity); - pool->idle += pool->capacity; + memMeterAdd(pool->meter.alloc, pool->chunk_capacity); + memMeterAdd(pool->meter.idle, pool->chunk_capacity); + pool->idle += pool->chunk_capacity; pool->chunkCount++; chunk->lastref = squid_curtime; lastPool = pool; @@ -171,9 +196,9 @@ static void memPoolChunkDestroy(MemPool * pool, MemChunk * chunk) { - memMeterDel(pool->meter.alloc, pool->capacity); - memMeterDel(pool->meter.idle, pool->capacity); - pool->idle -= pool->capacity; + memMeterDel(pool->meter.alloc, pool->chunk_capacity); + memMeterDel(pool->meter.idle, pool->chunk_capacity); + pool->idle -= pool->chunk_capacity; pool->chunkCount--; lastPool = pool; pool->allChunks = splay_delete(chunk, pool->allChunks, (SPLAYCMP *) memCompChunks); @@ -266,7 +291,63 @@ return; } -void +int +memPoolControl(void **pool, int cmd, size_t value) +{ + int ret = 0; + switch (cmd) { + case MPOOL_TUNE_CHUNKSIZE: + memPoolTune((MemPool *) pool, value, 0); + break; + case MPOOL_FLUSH_METERS: + memPoolFlushMetersAll((MemPool *) pool); + break; + case MPOOL_CLEAN_POOL: + memPoolClean((MemPool *) pool, value); + break; + case MPOOL_INIT: + memArrayInit(&PoolArray); + memset(&TheMeter, 0, sizeof(TheMeter)); + break; + case MPOOL_GET_INUSE: + ret = memPoolInUseCount((MemPool *) pool); + break; + case MPOOL_DESTROY: + memPoolDestroy((MemPool *) pool); + break; + case MPOOL_SYNC_HWATER: + memMeterSyncHWater((MemMeter *) pool); + break; + case MPOOL_GET_THEMETER: + *pool = &TheMeter; + break; + case MPOOL_GET_IDLE_LIMIT: + ret = mem_idle_limit; + break; + case MPOOL_SET_IDLE_LIMIT: + ret = mem_idle_limit - value; + mem_idle_limit = value; + break; + case MPOOL_GET_STATS: + ret = memPoolGetStats((MemPoolStats *) pool, value); + break; + case MPOOL_GET_TOTAL: + memPoolFlushMeters(NULL); + ret = TheMeter.alloc.level; + break; + case MPOOL_CLEAN_MODULE: + ret = memPoolCleanModule(); + break; + case MPOOL_GET_OVERHEAD: + ret = sizeof(Array) + PoolArray.capacity * sizeof(MemPool *); + break; + default: + ret = -1; + } + return ret; +} + +static void memPoolTune(MemPool * pool, size_t chunksize, int unused) { int cap; @@ -289,7 +370,7 @@ csize = ((csize + MEM_PAGE_SIZE - 1) / MEM_PAGE_SIZE) * MEM_PAGE_SIZE; /* round up to page size */ cap = csize / pool->obj_size; - pool->capacity = cap; + pool->chunk_capacity = cap; pool->chunk_size = csize; } @@ -306,7 +387,7 @@ memPoolTune(pool, MEM_CHUNK_SIZE, 0); pool->memPID = ++Pool_id_counter; - memArrayAppend(PoolArray, pool); + memArrayAppend(&PoolArray, pool); return pool; } @@ -314,13 +395,13 @@ * warning: we do not clean this entry from Pools assuming memPoolDestroy * is used at the end of the program only */ -void +static void memPoolDestroy(MemPool * pool) { assert(pool); } -void +static void memPoolFlushMeters(MemPool * pool) { size_t calls; @@ -390,9 +471,10 @@ } + /* removes empty Chunks from pool */ -void -memPoolClean(MemPool * pool, time_t maxage) +static void +memPoolCleanOne(MemPool * pool, time_t maxage) { MemChunk *chunk, *freechunk, *listTail; void **Free; @@ -453,7 +535,7 @@ while (chunk->next) { chunk->next->nextFreeChunk = NULL; - if (chunk->next->inuse_count < pool->capacity) { + if (chunk->next->inuse_count < pool->chunk_capacity) { listTail = pool->nextFreeChunk; while (listTail->nextFreeChunk) { if (chunk->next->inuse_count > listTail->nextFreeChunk->inuse_count) @@ -469,13 +551,118 @@ chunk = chunk->next; } /* We started from 2nd chunk. If first chunk is full, remove it */ - if (pool->nextFreeChunk->inuse_count == pool->capacity) + if (pool->nextFreeChunk->inuse_count == pool->chunk_capacity) pool->nextFreeChunk = pool->nextFreeChunk->nextFreeChunk; return; } -int +static void +memPoolClean(MemPool * onePool, time_t maxage) +{ + int i; + MemPool *pool; + int shift = 1; + if (onePool) + return memPoolCleanOne(onePool, maxage); + + memPoolFlushMetersAll(NULL); + if (TheMeter.idle.level > mem_idle_limit) + maxage = shift = 0; + for (i = 0; i < PoolArray.count; i++) { + pool = PoolArray.items[i]; + if (pool->meter.idle.level > (pool->chunk_capacity << shift)) { + memPoolCleanOne(pool, maxage); + } + } +} + +/* updates all pool counters, and recreates TheMeter totals from all pools */ +static void +memPoolFlushMetersAll(MemPool * onePool) +{ + int i; + MemPool *pool; + if (onePool) + return memPoolFlushMeters(onePool); + + TheMeter.alloc.level = 0; + TheMeter.inuse.level = 0; + TheMeter.idle.level = 0; + TheMeter.gb_saved.count = 0; + TheMeter.gb_saved.bytes = 0; + for (i = 0; i < PoolArray.count; i++) { + pool = PoolArray.items[i]; + memPoolFlushMeters(pool); + memMeterAdd(TheMeter.alloc, pool->meter.alloc.level * pool->obj_size); + memMeterAdd(TheMeter.inuse, pool->meter.inuse.level * pool->obj_size); + memMeterAdd(TheMeter.idle, pool->meter.idle.level * pool->obj_size); + TheMeter.gb_saved.count += pool->meter.gb_saved.count; + TheMeter.gb_saved.bytes += pool->meter.gb_saved.count * pool->obj_size; + pool->meter.gb_saved.bytes = pool->meter.gb_saved.count * pool->obj_size; + } +} + +static int +memPoolCleanModule(void) +{ + int i; + int dirty_count = 0; + for (i = 0; i < PoolArray.count; i++) { + MemPool *pool = PoolArray.items[i]; + if (memPoolInUseCount(pool)) { + dirty_count++; + } else { + memPoolDestroy(pool); + } + } + return dirty_count; +} + +static int +memPoolGetStats(MemPoolStats * mp_st, int index) +{ + MemPool *pool; + MemChunk *chunk; + if (index < 0) + return -1; + if (index > PoolArray.count) + return -2; + if (index == PoolArray.count) + return 0; + pool = PoolArray.items[index]; + mp_st->pool = pool; + if (!pool) + return index + 1; + memPoolClean(pool, (time_t) 555555); /* don't want to get chunks released before reporting */ + mp_st->label = pool->label; + mp_st->meter = &pool->meter; + mp_st->obj_size = pool->obj_size; + mp_st->chunk_capacity = pool->chunk_capacity; + + mp_st->chunks_alloc = pool->chunkCount; + mp_st->chunks_partial = 0; + mp_st->chunks_free = 0; + mp_st->overhead = sizeof(MemPool) + sizeof(MemPool *) + pool->chunkCount * sizeof(MemChunk); + + chunk = pool->Chunks; + while (chunk) { + if (chunk->inuse_count == 0) + mp_st->chunks_free++; + else if (chunk->inuse_count < pool->chunk_capacity) + mp_st->chunks_partial++; + chunk = chunk->next; + } + mp_st->chunks_inuse = pool->chunkCount - mp_st->chunks_free; + + mp_st->items_alloc = pool->meter.alloc.level; + mp_st->items_inuse = pool->meter.inuse.level; + mp_st->items_idle = pool->meter.idle.level; + + return index + 1; +} + +static int memPoolInUseCount(const MemPool * pool) { assert(pool); @@ -483,13 +670,11 @@ return pool->meter.inuse.level; } -void +static void memArrayInit(Array * a) { assert(a); memset(a, 0, sizeof(Array)); - assert(PoolArray == NULL); - PoolArray = a; } #if UNUSED_CODE Index: squid/src/MemPoolStats.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/MemPoolStats.c,v retrieving revision 1.1.2.16 retrieving revision 1.1.2.17 diff -u -r1.1.2.16 -r1.1.2.17 --- squid/src/MemPoolStats.c 1 May 2001 00:05:29 -0000 1.1.2.16 +++ squid/src/MemPoolStats.c 2 May 2001 20:21:59 -0000 1.1.2.17 @@ -33,28 +33,27 @@ * */ - #include "squid.h" #include "Stack.h" #include "MemPool.h" /* module globals */ +void memConfigure(void); +void memPoolCleanIdlePools(void *unused); +void memInitModule(void); +void memCleanModule(void); +void memReport(StoreEntry * e); /* module locals */ -static Array Pools; static double clean_interval = 15.0; /* time to live of idle chunk before release */ static double xm_time = 0; static double xm_deltat = 0; /* huge constant to set mem_idle_limit to "unlimited" */ static const size_t mem_unlimited_size = 2 * 1024 * MB; -static size_t mem_idle_limit = 0; -static MemPoolMeter TheMeter; /* local prototypes */ -static void memPoolDescribe(const MemPool * pool); -static void memPoolReport(const MemPool * pool, int freecount, int partial, StoreEntry * e); -static void memPoolFlushMetersAllPools(void); +static void memPoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, StoreEntry * e); static double toMB(size_t size) @@ -68,20 +67,13 @@ return (size + 1024 - 1) / 1024; } -size_t -memPoolsTotalAllocated(void) -{ - memPoolFlushMetersAllPools(); - return TheMeter.alloc.level; -} - /* Initialization */ /* XXX This is NOT statistics. Does NOT belong here. */ void memConfigure(void) { - size_t new_pool_limit = mem_idle_limit; + size_t new_pool_limit; /* set to configured value first */ if (!Config.onoff.mem_pools) new_pool_limit = 0; @@ -89,86 +81,36 @@ new_pool_limit = Config.MemPools.limit; else new_pool_limit = mem_unlimited_size; - /* shrink memory pools if needed */ - if (TheMeter.idle.level > new_pool_limit) { + if (memPoolSetIdleLimit(new_pool_limit) > 0) debug(63, 1) ("Shrinking idle mem pools to %.2f MB\n", toMB(new_pool_limit)); - /* will do that from event handler later */ - } - mem_idle_limit = new_pool_limit; -} - -/* updates all pool counters, and recreates TheMeter totals from all pools */ -static void -memPoolFlushMetersAllPools(void) -{ - int i; - MemPool *pool; - TheMeter.alloc.level = 0; - TheMeter.inuse.level = 0; - TheMeter.idle.level = 0; - TheMeter.gb_saved.count = 0; - TheMeter.gb_saved.bytes = 0; - for (i = 0; i < Pools.count; i++) { - pool = Pools.items[i]; - memPoolFlushMeters(pool); - memMeterAdd(TheMeter.alloc, pool->meter.alloc.level * pool->obj_size); - memMeterAdd(TheMeter.inuse, pool->meter.inuse.level * pool->obj_size); - memMeterAdd(TheMeter.idle, pool->meter.idle.level * pool->obj_size); - TheMeter.gb_saved.count += pool->meter.gb_saved.count; - TheMeter.gb_saved.bytes += pool->meter.gb_saved.count * pool->obj_size; - pool->meter.gb_saved.bytes = pool->meter.gb_saved.count * pool->obj_size; - } } /* XXX This is NOT statistics. Does NOT belong here. */ void memPoolCleanIdlePools(void *unused) { - int i; - MemPool *pool; - int shift = 1; - time_t maxage = clean_interval; - - memPoolFlushMetersAllPools(); - if (TheMeter.idle.level > mem_idle_limit) - maxage = shift = 0; - for (i = 0; i < Pools.count; i++) { - pool = Pools.items[i]; - if (pool->meter.idle.level > (pool->capacity << shift)) { - memPoolClean(pool, maxage); - } - } + memPoolClean(NULL, clean_interval); eventAdd("memPoolCleanIdlePools", memPoolCleanIdlePools, NULL, clean_interval, 1); } void memInitModule(void) { - memset(&TheMeter, 0, sizeof(TheMeter)); - memArrayInit(&Pools); debug(63, 1) ("Memory pools are '%s'; limit: %.2f MB\n", - (Config.onoff.mem_pools ? "on" : "off"), toMB(mem_idle_limit)); + (Config.onoff.mem_pools ? "on" : "off"), toMB(memPoolIdleLimit())); xm_time = current_dtime; } void memCleanModule(void) { - int i; int dirty_count = 0; - for (i = 0; i < Pools.count; i++) { - MemPool *pool = Pools.items[i]; - if (memPoolInUseCount(pool)) { - memPoolDescribe(pool); - dirty_count++; - } else { - memPoolDestroy(pool); - } - } + dirty_count = memPoolCleanModule(); if (dirty_count) debug(63, 2) ("memCleanModule: %d pools are left dirty\n", dirty_count); } +#if UNUSED_CODE /* to-do: make debug level a parameter? */ static void memPoolDescribe(const MemPool * pool) @@ -179,93 +121,79 @@ toKB(pool->obj_size * pool->meter.inuse.level)); } +#endif + /* MemPoolMeter */ static void -memPoolMeterReport(const MemPoolMeter * pm, size_t obj_size, - int alloc_count, int inuse_count, int idle_count, StoreEntry * e) +memPoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, StoreEntry * e) { - assert(pm); + int excess; + int needed = 0; + MemPoolMeter *pm = mp_st->meter; + + storeAppendPrintf(e, "%-20s\t %4d\t ", + mp_st->label, mp_st->obj_size); + + /* Chunks */ + storeAppendPrintf(e, "%4d\t %4d\t ", + toKB(mp_st->obj_size * mp_st->chunk_capacity), mp_st->chunk_capacity); + + if (mp_st->chunk_capacity) { + needed = mp_st->items_inuse / mp_st->chunk_capacity; + if (mp_st->items_inuse % mp_st->chunk_capacity) + needed++; + excess = mp_st->chunks_inuse - needed; + } + storeAppendPrintf(e, "%4d\t %4d\t %4d\t %4d\t %.1f\t ", + mp_st->chunks_alloc, mp_st->chunks_inuse, mp_st->chunks_free, mp_st->chunks_partial, + xpercent(excess, needed)); +/* + * Fragmentation calculation: + * needed = inuse.level / chunk_capacity + * excess = used - needed + * fragmentation = excess / needed * 100% + * + * Fragm = (alloced - (inuse / obj_ch) ) / alloced + */ + storeAppendPrintf(e, "%d\t %d\t %d\t %.2f\t %.1f\t" /* alloc */ "%d\t %d\t %d\t %.1f\t" /* in use */ "%d\t %d\t %d\t" /* idle */ "%.0f\t %.1f\t %.1f\t %.1f\n", /* saved */ /* alloc */ - alloc_count, - toKB(obj_size * pm->alloc.level), - toKB(obj_size * pm->alloc.hwater_level), + mp_st->items_alloc, + toKB(mp_st->obj_size * pm->alloc.level), + toKB(mp_st->obj_size * pm->alloc.hwater_level), (double) ((squid_curtime - pm->alloc.hwater_stamp) / 3600.), - xpercent(obj_size * pm->alloc.level, TheMeter.alloc.level), + xpercent(mp_st->obj_size * pm->alloc.level, AllMeter->alloc.level), /* in use */ - inuse_count, - toKB(obj_size * pm->inuse.level), - toKB(obj_size * pm->inuse.hwater_level), + mp_st->items_inuse, + toKB(mp_st->obj_size * pm->inuse.level), + toKB(mp_st->obj_size * pm->inuse.hwater_level), xpercent(pm->inuse.level, pm->alloc.level), /* idle */ - idle_count, - toKB(obj_size * pm->idle.level), - toKB(obj_size * pm->idle.hwater_level), + mp_st->items_idle, + toKB(mp_st->obj_size * pm->idle.level), + toKB(mp_st->obj_size * pm->idle.hwater_level), /* saved */ pm->gb_saved.count, - xpercent(pm->gb_saved.count, TheMeter.gb_saved.count), - xpercent(pm->gb_saved.bytes, TheMeter.gb_saved.bytes), + xpercent(pm->gb_saved.count, AllMeter->gb_saved.count), + xpercent(pm->gb_saved.bytes, AllMeter->gb_saved.bytes), xdiv(pm->gb_saved.count - pm->gb_osaved.count, xm_deltat)); - ((MemPoolMeter *) pm)->gb_osaved.count = pm->gb_saved.count; -} - -static void -memPoolReport(const MemPool * pool, int freecount, int partial, StoreEntry * e) -{ - int excess, needed; - int inuse; - assert(pool); - storeAppendPrintf(e, "%-20s\t %4d\t ", - pool->label, pool->obj_size); - storeAppendPrintf(e, "%4d\t %4d\t ", - toKB(pool->obj_size * pool->capacity), pool->capacity); - - inuse = pool->chunkCount - freecount; - - if (pool->meter.inuse.level % pool->capacity) - needed = pool->meter.inuse.level / pool->capacity + 1; - else - needed = pool->meter.inuse.level / pool->capacity; - - excess = inuse - needed; - - storeAppendPrintf(e, "%4d\t %4d\t %4d\t %4d\t %.1f\t ", - pool->chunkCount, inuse, freecount, partial, - xpercent(excess, needed)); -/* - * Fragmentation calculation: - * needed = inuse.level / capacity - * excess = used - needed - * fragmentation = excess / needed * 100% - * - * Fragm = (alloced - (inuse / obj_ch) ) / alloced - */ - memPoolMeterReport(&pool->meter, pool->obj_size, - pool->meter.alloc.level, pool->meter.inuse.level, pool->meter.idle.level, - e); + pm->gb_osaved.count = pm->gb_saved.count; } void memReport(StoreEntry * e) { - size_t overhd_size = 0; - int alloc_count = 0; - int inuse_count = 0; - int idle_count = 0; - int chunk_count = 0; - int nuse_count = 0; - int free_count = 0; - int part_count = 0; - MemChunk *chunk; - int freecount; - int partial; - int inuse; int i; + static char buf[64]; + static MemPoolStats mp_stats; + static MemPoolStats mp_total; + static MemPoolMeter *AllMeter; + /* caption */ storeAppendPrintf(e, "Current memory usage:\n"); /* heading */ @@ -287,52 +215,42 @@ "(#)\t %%cnt\t %%vol\t" "(#) / sec\t" "\n"); - /* main table */ xm_deltat = current_dtime - xm_time; xm_time = current_dtime; - memPoolFlushMetersAllPools(); - for (i = 0; i < Pools.count; i++) { - MemPool *pool = Pools.items[i]; - memPoolClean(pool, (time_t) 555555); /* don't want to get chunks released before reporting */ - if (pool->meter.inuse.hwater_level > 0) { /* this pool has been used */ - freecount = partial = 0; - chunk = pool->Chunks; - while (chunk) { - if (chunk->inuse_count == 0) - freecount++; - else if (chunk->inuse_count < pool->capacity) - partial++; - chunk = chunk->next; - } - inuse = pool->chunkCount - freecount; - memPoolReport(pool, freecount, partial, e); - - /* all Chunks */ - free_count += freecount; - part_count += partial; - nuse_count += inuse; - chunk_count += pool->chunkCount; - - /* all obj items */ - alloc_count += pool->meter.alloc.level; - inuse_count += pool->meter.inuse.level; - idle_count += pool->meter.idle.level; - } - overhd_size += sizeof(MemPool) + sizeof(MemPool *) + - strlen(pool->label) + 1 + - pool->chunkCount * sizeof(MemChunk); + memPoolFlushMeters(NULL); + + /* prepare Totals report line */ + memset(&mp_total, 0, sizeof(MemPoolStats)); + memPoolGetTheMeter(&AllMeter); + mp_total.label = "Total"; + mp_total.meter = AllMeter; + mp_total.obj_size = 1; + + /* main table */ + i = 0; + while (memPoolGetStats(&mp_stats, i++)) { + if (!mp_stats.pool) /* pool destroyed */ + continue; + if (mp_stats.pool->meter.inuse.hwater_level > 0) /* this pool has been used */ + memPoolReport(&mp_stats, AllMeter, e); + mp_total.chunks_alloc += mp_stats.chunks_alloc; + mp_total.chunks_free += mp_stats.chunks_free; + mp_total.chunks_inuse += mp_stats.chunks_inuse; + mp_total.chunks_partial += mp_stats.chunks_partial; + + mp_total.items_alloc += mp_stats.items_alloc; + mp_total.items_inuse += mp_stats.items_inuse; + mp_total.items_idle += mp_stats.items_idle; + mp_total.overhead += mp_stats.overhead + strlen(mp_stats.label) + 1; } - overhd_size += sizeof(Pools) + Pools.capacity * sizeof(MemPool *); - /* totals */ - storeAppendPrintf(e, "%-20s\t %-4s\t ", "Total", "-"); - storeAppendPrintf(e, "- \t -\t %4d\t %4d\t %4d\t %4d\t -\t ", - chunk_count, nuse_count, free_count, part_count); + mp_total.overhead += memPoolGetOverhead(); + memPoolReport(&mp_total, AllMeter, e); - memPoolMeterReport(&TheMeter, 1, alloc_count, inuse_count, idle_count, e); - storeAppendPrintf(e, "Cumulative allocated volume: %.0f\n", TheMeter.gb_saved.bytes); + /* Cumulative */ + storeAppendPrintf(e, "Cumulative allocated volume: %s\n", double_to_str(buf, 64, AllMeter->gb_saved.bytes)); /* overhead */ storeAppendPrintf(e, "Current overhead: %d bytes (%.3f%%)\n", - overhd_size, xpercent(overhd_size, TheMeter.inuse.level)); + mp_total.overhead, xpercent(mp_total.overhead, AllMeter->inuse.level)); /* limits */ - storeAppendPrintf(e, "Idle pool limit: %.2f MB\n", toMB(mem_idle_limit)); + storeAppendPrintf(e, "Idle pool limit: %.2f MB\n", toMB(memPoolIdleLimit())); } Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.23.4.6 retrieving revision 1.23.4.7 diff -u -r1.23.4.6 -r1.23.4.7 --- squid/src/protos.h 30 Apr 2001 19:35:30 -0000 1.23.4.6 +++ squid/src/protos.h 2 May 2001 20:21:59 -0000 1.23.4.7 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.23.4.6 2001/04/30 19:35:30 akroonmaa Exp $ + * $Id: protos.h,v 1.23.4.7 2001/05/02 20:21:59 akroonmaa Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -833,11 +833,10 @@ extern void memCheckInit(void); /* MemPool */ +extern int memPoolControl(void **pool, int cmd, size_t value); extern MemPool *memPoolCreate(const char *label, size_t obj_size); -extern void memPoolDestroy(MemPool * pool); extern void *memPoolAlloc(MemPool * pool); extern void memPoolFree(MemPool * pool, void *obj); -extern int memPoolInUseCount(const MemPool * pool); /* Mem */ extern void memReport(StoreEntry * e);