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)); storeAppendPrintf(sentry, "\n"); }
void cacheDigestReport(CacheDigest * cd, const char *label, StoreEntry * e) { CacheDigestStats stats; assert(cd && e); cacheDigestStats(cd, &stats); storeAppendPrintf(e, "%s digest: size: %d bytes\n", label ? label : "", stats.bit_count / 8 ); storeAppendPrintf(e, "\t entries: count: %d capacity: %d util: %d%%\n", cd->count, cd->capacity, xpercentInt(cd->count, cd->capacity) ); storeAppendPrintf(e, "\t deletion attempts: %d\n", cd->del_count ); storeAppendPrintf(e, "\t bits: per entry: %d on: %d capacity: %d util: %d%%\n", cd->bits_per_entry, stats.bit_on_count, stats.bit_count, xpercentInt(stats.bit_on_count, stats.bit_count) ); storeAppendPrintf(e, "\t bit-seq: count: %d avg.len: %.2f\n", stats.bseq_count, xdiv(stats.bseq_len_sum, stats.bseq_count) ); }
void cacheDigestGuessStatsReport(const cd_guess_stats * stats, StoreEntry * sentry, const char *label) { const int true_count = stats->true_hits + stats->true_misses; const int false_count = stats->false_hits + stats->false_misses; const int hit_count = stats->true_hits + stats->false_hits; const int miss_count = stats->true_misses + stats->false_misses; const int tot_count = true_count + false_count; assert(label); assert(tot_count == hit_count + miss_count); /* paranoid */ if (!tot_count) { storeAppendPrintf(sentry, "no guess stats for %s available\n", label); return; } storeAppendPrintf(sentry, "Digest guesses stats for %s:\n", label); storeAppendPrintf(sentry, "guess\t hit\t\t miss\t\t total\t\t\n"); storeAppendPrintf(sentry, " \t #\t %%\t #\t %%\t #\t %%\t\n"); storeAppendPrintf(sentry, "true\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", stats->true_hits, xpercent(stats->true_hits, tot_count), stats->true_misses, xpercent(stats->true_misses, tot_count), true_count, xpercent(true_count, tot_count)); storeAppendPrintf(sentry, "false\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", stats->false_hits, xpercent(stats->false_hits, tot_count), stats->false_misses, xpercent(stats->false_misses, tot_count), false_count, xpercent(false_count, tot_count)); storeAppendPrintf(sentry, "all\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", hit_count, xpercent(hit_count, tot_count), miss_count, xpercent(miss_count, tot_count), tot_count, xpercent(tot_count, tot_count)); storeAppendPrintf(sentry, "\tclose_hits: %d ( %d%%) /* cd said hit, doc was in the peer cache, but we got a miss */\n", stats->close_hits, xpercentInt(stats->close_hits, stats->false_hits)); }
int cacheDigestBitUtil(const CacheDigest * cd) { CacheDigestStats stats; assert(cd); cacheDigestStats(cd, &stats); return xpercentInt(stats.bit_on_count, stats.bit_count); }
/* returns true if we actually resized the digest */ static int storeDigestResize(void) { const int cap = storeDigestCalcCap(); int diff; assert(store_digest); diff = abs(cap - store_digest->capacity); debug(71, 2) ("storeDigestResize: %d -> %d; change: %d (%d%%)\n", store_digest->capacity, cap, diff, xpercentInt(diff, store_digest->capacity)); /* avoid minor adjustments */ if (diff <= store_digest->capacity / 10) { debug(71, 2) ("storeDigestResize: small change, will not resize.\n"); return 0; } else { debug(71, 2) ("storeDigestResize: big change, resizing.\n"); cacheDigestChangeCap(store_digest, cap); return 1; } }
static void cacheQueryReport(Cache * cache, CacheQueryStats * stats) { fprintf(stdout, "%s: peer queries: %d (%d%%)\n", cache->name, stats->query_count, xpercentInt(stats->query_count, cache->req_count) ); fprintf(stdout, "%s: t-hit: %d (%d%%) t-miss: %d (%d%%) t-*: %d (%d%%)\n", cache->name, stats->true_hit_count, xpercentInt(stats->true_hit_count, stats->query_count), stats->true_miss_count, xpercentInt(stats->true_miss_count, stats->query_count), stats->true_hit_count + stats->true_miss_count, xpercentInt(stats->true_hit_count + stats->true_miss_count, stats->query_count) ); fprintf(stdout, "%s: f-hit: %d (%d%%) f-miss: %d (%d%%) f-*: %d (%d%%)\n", cache->name, stats->false_hit_count, xpercentInt(stats->false_hit_count, stats->query_count), stats->false_miss_count, xpercentInt(stats->false_miss_count, stats->query_count), stats->false_hit_count + stats->false_miss_count, xpercentInt(stats->false_hit_count + stats->false_miss_count, stats->query_count) ); }
static int peerDigestSetCBlock(PeerDigest * pd, const char *buf) { StoreDigestCBlock cblock; int freed_size = 0; const char *host = strBuf(pd->host); xmemcpy(&cblock, buf, sizeof(cblock)); /* network -> host conversions */ cblock.ver.current = ntohs(cblock.ver.current); cblock.ver.required = ntohs(cblock.ver.required); cblock.capacity = ntohl(cblock.capacity); cblock.count = ntohl(cblock.count); cblock.del_count = ntohl(cblock.del_count); cblock.mask_size = ntohl(cblock.mask_size); debug(72, 2) ("got digest cblock from %s; ver: %d (req: %d)\n", host, (int) cblock.ver.current, (int) cblock.ver.required); debug(72, 2) ("\t size: %d bytes, e-cnt: %d, e-util: %d%%\n", cblock.mask_size, cblock.count, xpercentInt(cblock.count, cblock.capacity)); /* check version requirements (both ways) */ if (cblock.ver.required > CacheDigestVer.current) { debug(72, 1) ("%s digest requires version %d; have: %d\n", host, cblock.ver.required, CacheDigestVer.current); return 0; } if (cblock.ver.current < CacheDigestVer.required) { debug(72, 1) ("%s digest is version %d; we require: %d\n", host, cblock.ver.current, CacheDigestVer.required); return 0; } /* check consistency */ if (cblock.ver.required > cblock.ver.current || cblock.mask_size <= 0 || cblock.capacity <= 0 || cblock.bits_per_entry <= 0 || cblock.hash_func_count <= 0) { debug(72, 0) ("%s digest cblock is corrupted.\n", host); return 0; } /* check consistency further */ if (cblock.mask_size != cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)) { debug(72, 0) ("%s digest cblock is corrupted (mask size mismatch: %d ? %d).\n", host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)); return 0; } /* there are some things we cannot do yet */ if (cblock.hash_func_count != CacheDigestHashFuncCount) { debug(72, 0) ("%s digest: unsupported #hash functions: %d ? %d.\n", host, cblock.hash_func_count, CacheDigestHashFuncCount); return 0; } /* * no cblock bugs below this point */ /* check size changes */ if (pd->cd && cblock.mask_size != pd->cd->mask_size) { debug(72, 2) ("%s digest changed size: %d -> %d\n", host, cblock.mask_size, pd->cd->mask_size); freed_size = pd->cd->mask_size; cacheDigestDestroy(pd->cd); pd->cd = NULL; } if (!pd->cd) { debug(72, 2) ("creating %s digest; size: %d (%+d) bytes\n", host, cblock.mask_size, (int) (cblock.mask_size - freed_size)); pd->cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry); if (cblock.mask_size >= freed_size) kb_incr(&Counter.cd.memory, cblock.mask_size - freed_size); } assert(pd->cd); /* these assignments leave us in an inconsistent state until we finish reading the digest */ pd->cd->count = cblock.count; pd->cd->del_count = cblock.del_count; return 1; }