/*
- * $Id: mem.cc,v 1.14 1998/03/07 02:05:29 wessels Exp $
+ * $Id: mem.cc,v 1.15 1998/03/07 20:46:18 rousskov Exp $
*
* DEBUG: section 13 High Level Memory Pool Management
* AUTHOR: Harvest Derived
static MemPool *MemPools[MEM_MAX];
+/* string pools */
+#define mem_str_pool_count 3
+static const struct {
+ const char *name;
+ size_t obj_size;
+} StrPoolsAttrs[mem_str_pool_count] = {
+ { "Short Strings", 36, }, /* to fit rfc1123 and similar */
+ { "Medium Strings", 128, }, /* to fit most urls */
+ { "Long Strings", 512 } /* other */
+};
+static struct { MemPool *pool; } StrPools[mem_str_pool_count];
+static MemMeter StrCountMeter;
+static MemMeter StrVolumeMeter;
+
+
+/* local routines */
+
/* we have a limit on _total_ amount of idle memory so we ignore max_pages for now */
static void
memDataInit(mem_type type, const char *name, size_t size, int max_pages_notused)
MemPools[type] = memPoolCreate(name, size);
}
+static void
+memStringStats(StoreEntry * sentry)
+{
+ const char *pfmt = "%-20s\t %d\t %d\n";
+ int i;
+ int pooled_count = 0;
+ size_t pooled_volume = 0;
+ /* heading */
+ storeAppendPrintf(sentry,
+ "String Pool\t Impact\t\t\n"
+ " \t (%%strings)\t (%%volume)\n");
+ /* table body */
+ for (i = 0; i < mem_str_pool_count; i++) {
+ const MemPool *pool = StrPools[i].pool;
+ const int plevel = pool->meter.inuse.level;
+ storeAppendPrintf(sentry, pfmt,
+ pool->label,
+ xpercentInt(plevel, StrCountMeter.level),
+ xpercentInt(plevel*pool->obj_size, StrVolumeMeter.level));
+ pooled_count += plevel;
+ pooled_volume += plevel*pool->obj_size;
+ }
+ /* malloc strings */
+ storeAppendPrintf(sentry, pfmt,
+ "Other Strings",
+ xpercentInt(StrCountMeter.level-pooled_count, StrCountMeter.level),
+ xpercentInt(StrVolumeMeter.level-pooled_volume, StrVolumeMeter.level));
+}
+
static void
memStats(StoreEntry * sentry)
{
storeBuffer(sentry);
memReport(sentry);
- /* memStringStats(sentry); */
+ memStringStats(sentry);
storeBufferFlush(sentry);
}
-
/*
- * PUBLIC ROUTINES
+ * public routines
*/
+
/* find appropriate pool and use it (pools always init buffer with 0s) */
void *
memAllocate(mem_type type)
memPoolFree(MemPools[type], p);
}
+/* allocate a variable size buffer using best-fit pool */
+void *
+memAllocBuf(size_t net_size, size_t *gross_size)
+{
+ int i;
+ MemPool *pool = NULL;
+ assert(gross_size);
+ for (i = 0; i < mem_str_pool_count; i++) {
+ if (net_size <= StrPoolsAttrs[i].obj_size) {
+ pool = StrPools[i].pool;
+ break;
+ }
+ }
+ *gross_size = pool ? pool->obj_size : net_size;
+ assert(*gross_size >= net_size);
+ memMeterInc(StrCountMeter);
+ memMeterAdd(StrVolumeMeter, *gross_size);
+ return pool ? memPoolAlloc(pool) : xcalloc(1, net_size);
+}
+
+/* free buffer allocated with memAllocBuf() */
+void
+memFreeBuf(size_t size, void *buf)
+{
+ int i;
+ MemPool *pool = NULL;
+ assert(size && buf);
+ for (i = 0; i < mem_str_pool_count; i++) {
+ if (size <= StrPoolsAttrs[i].obj_size) {
+ assert(size == StrPoolsAttrs[i].obj_size);
+ pool = StrPools[i].pool;
+ break;
+ }
+ }
+ memMeterDec(StrCountMeter);
+ memMeterDel(StrVolumeMeter, size);
+ pool ? memPoolFree(pool, buf) : xfree(buf);
+}
+
void
memInit(void)
{
+ int i;
mem_type t;
memInitModule();
/* set all pointers to null */
*/
assert(MemPools[t]);
}
+ /* init string pools */
+ for (i = 0; i < mem_str_pool_count; i++) {
+ StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size);
+ }
cachemgrRegister("mem",
"Memory Utilization",
memStats, 0);
void
memClean()
{
- mem_type t;
- int dirty_count = 0;
- for (t = MEM_NONE + 1; t < MEM_MAX; t++) {
- MemPool *pool = MemPools[t];
- if (memPoolInUseCount(pool)) {
- memPoolDescribe(pool);
- dirty_count++;
- }
- }
- if (dirty_count)
- debug(13, 2) ("memClean: %d pools are left dirty\n", dirty_count);
- else
- memCleanModule(); /* will free chunks and stuff */
+ memCleanModule();
}
-
int
memInUse(mem_type type)
{