Commit a7f63500 authored by Rusty Russell's avatar Rusty Russell

alloc: implement alloc_visualize().

parent f6d21b50
......@@ -943,3 +943,129 @@ bool alloc_check(void *pool, unsigned long poolsize)
return true;
}
static unsigned long print_overhead(FILE *out, const char *desc,
unsigned long bytes,
unsigned long poolsize)
{
fprintf(out, "Overhead (%s): %lu bytes (%.3g%%)\n",
desc, bytes, 100.0 * bytes / poolsize);
return bytes;
}
static unsigned long count_list(struct header *head,
unsigned long off,
unsigned long *total_elems)
{
struct page_header *p;
unsigned long ret = 0;
while (off) {
p = from_off(head, off);
if (total_elems)
(*total_elems) += p->elements_used;
ret++;
off = p->next;
}
return ret;
}
static unsigned long visualize_bucket(FILE *out, struct header *head,
unsigned int bucket,
unsigned long poolsize)
{
unsigned long num_full, num_partial, num_pages, page_size,
elems, hdr_min, hdr_size, elems_per_page, overhead = 0;
elems_per_page = head->bs[bucket].elements_per_page;
/* If we used byte-based bitmaps, we could get pg hdr to: */
hdr_min = sizeof(struct page_header)
- sizeof(((struct page_header *)0)->used)
+ align_up(elems_per_page, CHAR_BIT) / CHAR_BIT;
hdr_size = page_header_size(bucket / INTER_BUCKET_SPACE,
elems_per_page);
elems = 0;
num_full = count_list(head, head->bs[bucket].full_list, &elems);
num_partial = count_list(head, head->bs[bucket].page_list, &elems);
num_pages = num_full + num_partial;
if (!num_pages)
return 0;
fprintf(out, "Bucket %u (%lu bytes):"
" %lu full, %lu partial = %lu elements\n",
bucket, bucket_to_size(bucket), num_full, num_partial, elems);
/* Strict requirement of page header size. */
overhead += print_overhead(out, "page headers",
hdr_min * num_pages, poolsize);
/* Gap between minimal page header and actual start. */
overhead += print_overhead(out, "page post-header alignments",
(hdr_size - hdr_min) * num_pages, poolsize);
/* Between last element and end of page. */
page_size = 1UL << large_page_bits(poolsize);
if (!large_page_bucket(bucket, poolsize))
page_size >>= BITS_FROM_SMALL_TO_LARGE_PAGE;
overhead += print_overhead(out, "page tails",
(page_size - (hdr_size
+ (elems_per_page
* bucket_to_size(bucket))))
* num_pages, poolsize);
return overhead;
}
static void tiny_alloc_visualize(FILE *out, void *pool, unsigned long poolsize)
{
}
void alloc_visualize(FILE *out, void *pool, unsigned long poolsize)
{
struct header *head = pool;
unsigned long i, lp_bits, sp_bits, header_size, num_buckets, count,
overhead = 0;
fprintf(out, "Pool %p size %lu: (%s allocator)\n", pool, poolsize,
poolsize < MIN_USEFUL_SIZE ? "tiny" : "standard");
if (poolsize < MIN_USEFUL_SIZE) {
tiny_alloc_visualize(out, pool, poolsize);
return;
}
lp_bits = large_page_bits(poolsize);
sp_bits = lp_bits - BITS_FROM_SMALL_TO_LARGE_PAGE;
num_buckets = max_bucket(lp_bits);
header_size = sizeof(*head) + sizeof(head->bs) * (num_buckets-1);
fprintf(out, "Large page size %lu, small page size %lu.\n",
1UL << lp_bits, 1UL << sp_bits);
overhead += print_overhead(out, "unused pool tail",
poolsize % (1 << lp_bits), poolsize);
fprintf(out, "Main header %lu bytes (%lu small pages).\n",
header_size, align_up(header_size, 1 << sp_bits) >> sp_bits);
overhead += print_overhead(out, "partial header page",
align_up(header_size, 1 << sp_bits)
- header_size, poolsize);
/* Total large pages. */
i = count_bits(head->pagesize, poolsize >> lp_bits);
/* Used pages. */
count = i - count_list(head, head->large_free_list, NULL);
fprintf(out, "%lu/%lu large pages used (%.3g%%)\n",
count, i, count ? 100.0 * count / i : 0.0);
/* Total small pages. */
i = (poolsize >> lp_bits) - i;
/* Used pages */
count = i - count_list(head, head->small_free_list, NULL);
fprintf(out, "%lu/%lu small pages used (%.3g%%)\n",
count, i, count ? 100.0 * count / i : 0.0);
/* Summary of each bucket. */
fprintf(out, "%lu buckets:\n", num_buckets);
for (i = 0; i < num_buckets; i++)
overhead += visualize_bucket(out, head, i, poolsize);
print_overhead(out, "total", overhead, poolsize);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment