summaryrefslogtreecommitdiffstats
path: root/cmd/zdb/zdb.c
diff options
context:
space:
mode:
authorRobert Novak <[email protected]>2020-06-26 15:09:20 -0700
committerGitHub <[email protected]>2020-06-26 15:09:20 -0700
commitbfcbec6f5d8aad60365eaeacff21df92c04c26df (patch)
tree89e1fcc5ea8510db562dd768eff6f78474975224 /cmd/zdb/zdb.c
parent6b99fc0620f00fcfd201595b2bc6d279031dcb09 (diff)
Add block histogram to zdb
The block histogram tracks the changes to psize, lsize and asize both in the count of the number of blocks (by blocksize) and the total length of all of the blocks for that blocksize. It also keeps a running total of the cumulative size of all of the blocks up to each size to help determine the size of caching SSDs to be added to zfs hardware deployments. The block history counts and lengths are summarized in bins which are powers of two. Even rows with counts of zero are printed. This change is accessed by specifying one of two options: zdb -bbb pool zdb -Pbbb pool The first version prints the table in fixed size columns. The second prints in "parseable" output that can be placed into a CSV file. Fixed Column, nicenum output sample: block psize lsize asize size Count Length Cum. Count Length Cum. Count Length Cum. 512: 3.50K 1.75M 1.75M 3.43K 1.71M 1.71M 3.41K 1.71M 1.71M 1K: 3.65K 3.67M 5.43M 3.43K 3.44M 5.15M 3.50K 3.51M 5.22M 2K: 3.45K 6.92M 12.3M 3.41K 6.83M 12.0M 3.59K 7.26M 12.5M 4K: 3.44K 13.8M 26.1M 3.43K 13.7M 25.7M 3.49K 14.1M 26.6M 8K: 3.42K 27.3M 53.5M 3.41K 27.3M 53.0M 3.44K 27.6M 54.2M 16K: 3.43K 54.9M 108M 3.50K 56.1M 109M 3.42K 54.7M 109M 32K: 3.44K 110M 219M 3.41K 109M 218M 3.43K 110M 219M 64K: 3.41K 218M 437M 3.41K 218M 437M 3.44K 221M 439M 128K: 3.41K 437M 874M 3.70K 474M 911M 3.41K 437M 876M 256K: 3.41K 874M 1.71G 3.41K 874M 1.74G 3.41K 874M 1.71G 512K: 3.41K 1.71G 3.41G 3.41K 1.71G 3.45G 3.41K 1.71G 3.42G 1M: 3.41K 3.41G 6.82G 3.41K 3.41G 6.86G 3.41K 3.41G 6.83G 2M: 0 0 6.82G 0 0 6.86G 0 0 6.83G 4M: 0 0 6.82G 0 0 6.86G 0 0 6.83G 8M: 0 0 6.82G 0 0 6.86G 0 0 6.83G 16M: 0 0 6.82G 0 0 6.86G 0 0 6.83G Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Robert E. Novak <[email protected]> Closes: #9158 Closes #10315
Diffstat (limited to 'cmd/zdb/zdb.c')
-rw-r--r--cmd/zdb/zdb.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index 763a086ac..a329e4a83 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -4161,6 +4161,7 @@ static const char *zdb_ot_extname[] = {
};
#define ZB_TOTAL DN_MAX_LEVELS
+#define SPA_MAX_FOR_16M (SPA_MAXBLOCKSHIFT+1)
typedef struct zdb_cb {
zdb_blkstats_t zcb_type[ZB_TOTAL + 1][ZDB_OT_TOTAL + 1];
@@ -4168,6 +4169,15 @@ typedef struct zdb_cb {
uint64_t zcb_checkpoint_size;
uint64_t zcb_dedup_asize;
uint64_t zcb_dedup_blocks;
+ uint64_t zcb_psize_count[SPA_MAX_FOR_16M];
+ uint64_t zcb_lsize_count[SPA_MAX_FOR_16M];
+ uint64_t zcb_asize_count[SPA_MAX_FOR_16M];
+ uint64_t zcb_psize_len[SPA_MAX_FOR_16M];
+ uint64_t zcb_lsize_len[SPA_MAX_FOR_16M];
+ uint64_t zcb_asize_len[SPA_MAX_FOR_16M];
+ uint64_t zcb_psize_total;
+ uint64_t zcb_lsize_total;
+ uint64_t zcb_asize_total;
uint64_t zcb_embedded_blocks[NUM_BP_EMBEDDED_TYPES];
uint64_t zcb_embedded_histogram[NUM_BP_EMBEDDED_TYPES]
[BPE_PAYLOAD_SIZE + 1];
@@ -4191,6 +4201,172 @@ same_metaslab(spa_t *spa, uint64_t vdev, uint64_t off1, uint64_t off2)
return ((off1 >> ms_shift) == (off2 >> ms_shift));
}
+/*
+ * Used to simplify reporting of the histogram data.
+ */
+typedef struct one_histo {
+ char *name;
+ uint64_t *count;
+ uint64_t *len;
+ uint64_t cumulative;
+} one_histo_t;
+
+/*
+ * The number of separate histograms processed for psize, lsize and asize.
+ */
+#define NUM_HISTO 3
+
+/*
+ * This routine will create a fixed column size output of three different
+ * histograms showing by blocksize of 512 - 2^ SPA_MAX_FOR_16M
+ * the count, length and cumulative length of the psize, lsize and
+ * asize blocks.
+ *
+ * All three types of blocks are listed on a single line
+ *
+ * By default the table is printed in nicenumber format (e.g. 123K) but
+ * if the '-P' parameter is specified then the full raw number (parseable)
+ * is printed out.
+ */
+static void
+dump_size_histograms(zdb_cb_t *zcb)
+{
+ /*
+ * A temporary buffer that allows us to convert a number into
+ * a string using zdb_nicenumber to allow either raw or human
+ * readable numbers to be output.
+ */
+ char numbuf[32];
+
+ /*
+ * Define titles which are used in the headers of the tables
+ * printed by this routine.
+ */
+ const char blocksize_title1[] = "block";
+ const char blocksize_title2[] = "size";
+ const char count_title[] = "Count";
+ const char length_title[] = "Size";
+ const char cumulative_title[] = "Cum.";
+
+ /*
+ * Setup the histogram arrays (psize, lsize, and asize).
+ */
+ one_histo_t parm_histo[NUM_HISTO];
+
+ parm_histo[0].name = "psize";
+ parm_histo[0].count = zcb->zcb_psize_count;
+ parm_histo[0].len = zcb->zcb_psize_len;
+ parm_histo[0].cumulative = 0;
+
+ parm_histo[1].name = "lsize";
+ parm_histo[1].count = zcb->zcb_lsize_count;
+ parm_histo[1].len = zcb->zcb_lsize_len;
+ parm_histo[1].cumulative = 0;
+
+ parm_histo[2].name = "asize";
+ parm_histo[2].count = zcb->zcb_asize_count;
+ parm_histo[2].len = zcb->zcb_asize_len;
+ parm_histo[2].cumulative = 0;
+
+
+ (void) printf("\nBlock Size Histogram\n");
+ /*
+ * Print the first line titles
+ */
+ if (dump_opt['P'])
+ (void) printf("\n%s\t", blocksize_title1);
+ else
+ (void) printf("\n%7s ", blocksize_title1);
+
+ for (int j = 0; j < NUM_HISTO; j++) {
+ if (dump_opt['P']) {
+ if (j < NUM_HISTO - 1) {
+ (void) printf("%s\t\t\t", parm_histo[j].name);
+ } else {
+ /* Don't print trailing spaces */
+ (void) printf(" %s", parm_histo[j].name);
+ }
+ } else {
+ if (j < NUM_HISTO - 1) {
+ /* Left aligned strings in the output */
+ (void) printf("%-7s ",
+ parm_histo[j].name);
+ } else {
+ /* Don't print trailing spaces */
+ (void) printf("%s", parm_histo[j].name);
+ }
+ }
+ }
+ (void) printf("\n");
+
+ /*
+ * Print the second line titles
+ */
+ if (dump_opt['P']) {
+ (void) printf("%s\t", blocksize_title2);
+ } else {
+ (void) printf("%7s ", blocksize_title2);
+ }
+
+ for (int i = 0; i < NUM_HISTO; i++) {
+ if (dump_opt['P']) {
+ (void) printf("%s\t%s\t%s\t",
+ count_title, length_title, cumulative_title);
+ } else {
+ (void) printf("%7s%7s%7s",
+ count_title, length_title, cumulative_title);
+ }
+ }
+ (void) printf("\n");
+
+ /*
+ * Print the rows
+ */
+ for (int i = SPA_MINBLOCKSHIFT; i < SPA_MAX_FOR_16M; i++) {
+
+ /*
+ * Print the first column showing the blocksize
+ */
+ zdb_nicenum((1ULL << i), numbuf, sizeof (numbuf));
+
+ if (dump_opt['P']) {
+ printf("%s", numbuf);
+ } else {
+ printf("%7s:", numbuf);
+ }
+
+ /*
+ * Print the remaining set of 3 columns per size:
+ * for psize, lsize and asize
+ */
+ for (int j = 0; j < NUM_HISTO; j++) {
+ parm_histo[j].cumulative += parm_histo[j].len[i];
+
+ zdb_nicenum(parm_histo[j].count[i],
+ numbuf, sizeof (numbuf));
+ if (dump_opt['P'])
+ (void) printf("\t%s", numbuf);
+ else
+ (void) printf("%7s", numbuf);
+
+ zdb_nicenum(parm_histo[j].len[i],
+ numbuf, sizeof (numbuf));
+ if (dump_opt['P'])
+ (void) printf("\t%s", numbuf);
+ else
+ (void) printf("%7s", numbuf);
+
+ zdb_nicenum(parm_histo[j].cumulative,
+ numbuf, sizeof (numbuf));
+ if (dump_opt['P'])
+ (void) printf("\t%s", numbuf);
+ else
+ (void) printf("%7s", numbuf);
+ }
+ (void) printf("\n");
+ }
+}
+
static void
zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
dmu_object_type_t type)
@@ -4284,6 +4460,28 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
[BPE_GET_PSIZE(bp)]++;
return;
}
+ /*
+ * The binning histogram bins by powers of two up to
+ * SPA_MAXBLOCKSIZE rather than creating bins for
+ * every possible blocksize found in the pool.
+ */
+ int bin = highbit64(BP_GET_PSIZE(bp)) - 1;
+
+ zcb->zcb_psize_count[bin]++;
+ zcb->zcb_psize_len[bin] += BP_GET_PSIZE(bp);
+ zcb->zcb_psize_total += BP_GET_PSIZE(bp);
+
+ bin = highbit64(BP_GET_LSIZE(bp)) - 1;
+
+ zcb->zcb_lsize_count[bin]++;
+ zcb->zcb_lsize_len[bin] += BP_GET_LSIZE(bp);
+ zcb->zcb_lsize_total += BP_GET_LSIZE(bp);
+
+ bin = highbit64(BP_GET_ASIZE(bp)) - 1;
+
+ zcb->zcb_asize_count[bin]++;
+ zcb->zcb_asize_len[bin] += BP_GET_ASIZE(bp);
+ zcb->zcb_asize_total += BP_GET_ASIZE(bp);
if (dump_opt['L'])
return;
@@ -5645,6 +5843,11 @@ dump_block_stats(spa_t *spa)
}
}
}
+
+ /* Output a table summarizing block sizes in the pool */
+ if (dump_opt['b'] >= 2) {
+ dump_size_histograms(&zcb);
+ }
}
(void) printf("\n");