+
+/* Print statistics on BCACHE's memory usage and efficacity at
+ eliminating duplication. NAME should describe the kind of data
+ BCACHE holds. Statistics are printed using `printf_filtered' and
+ its ilk. */
+void
+print_bcache_statistics (struct bcache *c, char *type)
+{
+ int occupied_buckets;
+ int max_chain_length;
+ int median_chain_length;
+
+ /* Count the number of occupied buckets, and measure chain lengths. */
+ {
+ unsigned int b;
+ int *chain_length
+ = (int *) alloca (c->num_buckets * sizeof (*chain_length));
+
+ occupied_buckets = 0;
+
+ for (b = 0; b < c->num_buckets; b++)
+ {
+ struct bstring *s = c->bucket[b];
+
+ chain_length[b] = 0;
+
+ if (s)
+ {
+ occupied_buckets++;
+
+ while (s)
+ {
+ chain_length[b]++;
+ s = s->next;
+ }
+ }
+ }
+
+ /* To compute the median, we need the set of chain lengths sorted. */
+ qsort (chain_length, c->num_buckets, sizeof (chain_length[0]),
+ compare_ints);
+
+ if (c->num_buckets > 0)
+ {
+ max_chain_length = chain_length[c->num_buckets - 1];
+ median_chain_length = chain_length[c->num_buckets / 2];
+ }
+ else
+ {
+ max_chain_length = 0;
+ median_chain_length = 0;
+ }
+ }
+
+ printf_filtered (" Cached '%s' statistics:\n", type);
+ printf_filtered (" Total object count: %ld\n", c->total_count);
+ printf_filtered (" Unique object count: %lu\n", c->unique_count);
+ printf_filtered (" Percentage of duplicates, by count: ");
+ print_percentage (c->total_count - c->unique_count, c->total_count);
+ printf_filtered ("\n");
+
+ printf_filtered (" Total object size: %ld\n", c->total_size);
+ printf_filtered (" Unique object size: %ld\n", c->unique_size);
+ printf_filtered (" Percentage of duplicates, by size: ");
+ print_percentage (c->total_size - c->unique_size, c->total_size);
+ printf_filtered ("\n");
+
+ printf_filtered (" Total memory used by bcache, including overhead: %ld\n",
+ c->structure_size);
+ printf_filtered (" Percentage memory overhead: ");
+ print_percentage (c->structure_size - c->unique_size, c->unique_size);
+ printf_filtered (" Net memory savings: ");
+ print_percentage (c->total_size - c->structure_size, c->total_size);
+ printf_filtered ("\n");
+
+ printf_filtered (" Hash table size: %3d\n", c->num_buckets);
+ printf_filtered (" Hash table population: ");
+ print_percentage (occupied_buckets, c->num_buckets);
+ printf_filtered (" Median hash chain length: %3d\n",
+ median_chain_length);
+ printf_filtered (" Average hash chain length: ");
+ if (c->num_buckets > 0)
+ printf_filtered ("%3lu\n", c->unique_count / c->num_buckets);
+ else
+ printf_filtered ("(not applicable)\n");
+ printf_filtered (" Maximum hash chain length: %3d\n", max_chain_length);
+ printf_filtered ("\n");
+}