BUG/MINOR: cache: fix "show cache" output

The "show cache" command used to dump the header for each entry into into
the handler loop, making it repeated every ~16kB of output data. Additionally
chunk_appendf() was used instead of chunk_printf(), causing the output to
repeat already emitted lines, and the output size to grow in O(n^2). It used
to take several minutes to report tens of millions of objects from a small
cache containing only a few thousands. There was no more impact though.

This fix must be backported to 1.8.
This commit is contained in:
Willy Tarreau 2018-04-04 11:56:43 +02:00
parent b797ae1f15
commit afe1de5d98

View File

@ -963,9 +963,6 @@ static int cli_io_handler_show_cache(struct appctx *appctx)
struct cache* cache = appctx->ctx.cli.p0;
struct stream_interface *si = appctx->owner;
chunk_reset(&trash);
if (cache == NULL) {
cache = LIST_ELEM((caches).n, typeof(struct cache *), list);
}
@ -975,9 +972,14 @@ static int cli_io_handler_show_cache(struct appctx *appctx)
unsigned int next_key;
struct cache_entry *entry;
chunk_appendf(&trash, "%p: %s (shctx:%p, available blocks:%d)\n", cache, cache->id, shctx_ptr(cache), shctx_ptr(cache)->nbav);
next_key = appctx->ctx.cli.i0;
if (!next_key) {
chunk_printf(&trash, "%p: %s (shctx:%p, available blocks:%d)\n", cache, cache->id, shctx_ptr(cache), shctx_ptr(cache)->nbav);
if (ci_putchk(si_ic(si), &trash) == -1) {
si_applet_cant_put(si);
return 0;
}
}
appctx->ctx.cli.p0 = cache;
@ -987,11 +989,12 @@ static int cli_io_handler_show_cache(struct appctx *appctx)
node = eb32_lookup_ge(&cache->entries, next_key);
if (!node) {
shctx_unlock(shctx_ptr(cache));
appctx->ctx.cli.i0 = 0;
break;
}
entry = container_of(node, struct cache_entry, eb);
chunk_appendf(&trash, "%p hash:%u size:%u (%u blocks), refcount:%u, expire:%d\n", entry, (*(unsigned int *)entry->hash), block_ptr(entry)->len, block_ptr(entry)->block_count, block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec);
chunk_printf(&trash, "%p hash:%u size:%u (%u blocks), refcount:%u, expire:%d\n", entry, (*(unsigned int *)entry->hash), block_ptr(entry)->len, block_ptr(entry)->block_count, block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec);
next_key = node->key + 1;
appctx->ctx.cli.i0 = next_key;