]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/openzfs/cmd/raidz_test/raidz_bench.c
zfs: merge openzfs/zfs@3522f57b6 (master)
[FreeBSD/FreeBSD.git] / sys / contrib / openzfs / cmd / raidz_test / raidz_bench.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21
22 /*
23  * Copyright (C) 2016 Gvozden Nešković. All rights reserved.
24  */
25
26 #include <sys/zfs_context.h>
27 #include <sys/time.h>
28 #include <sys/wait.h>
29 #include <sys/zio.h>
30 #include <sys/vdev_raidz.h>
31 #include <sys/vdev_raidz_impl.h>
32 #include <stdio.h>
33
34 #include "raidz_test.h"
35
36 #define GEN_BENCH_MEMORY        (((uint64_t)1ULL)<<32)
37 #define REC_BENCH_MEMORY        (((uint64_t)1ULL)<<29)
38 #define BENCH_ASHIFT            12
39 #define MIN_CS_SHIFT            BENCH_ASHIFT
40 #define MAX_CS_SHIFT            SPA_MAXBLOCKSHIFT
41
42 static zio_t zio_bench;
43 static raidz_map_t *rm_bench;
44 static size_t max_data_size = SPA_MAXBLOCKSIZE;
45
46 static void
47 bench_init_raidz_map(void)
48 {
49         zio_bench.io_offset = 0;
50         zio_bench.io_size = max_data_size;
51
52         /*
53          * To permit larger column sizes these have to be done
54          * allocated using aligned alloc instead of zio_abd_buf_alloc
55          */
56         zio_bench.io_abd = raidz_alloc(max_data_size);
57
58         init_zio_abd(&zio_bench);
59 }
60
61 static void
62 bench_fini_raidz_maps(void)
63 {
64         /* tear down golden zio */
65         raidz_free(zio_bench.io_abd, max_data_size);
66         bzero(&zio_bench, sizeof (zio_t));
67 }
68
69 static inline void
70 run_gen_bench_impl(const char *impl)
71 {
72         int fn, ncols;
73         uint64_t ds, iter_cnt, iter, disksize;
74         hrtime_t start;
75         double elapsed, d_bw;
76
77         /* Benchmark generate functions */
78         for (fn = 0; fn < RAIDZ_GEN_NUM; fn++) {
79
80                 for (ds = MIN_CS_SHIFT; ds <= MAX_CS_SHIFT; ds++) {
81                         /* create suitable raidz_map */
82                         ncols = rto_opts.rto_dcols + fn + 1;
83                         zio_bench.io_size = 1ULL << ds;
84
85                         if (rto_opts.rto_expand) {
86                                 rm_bench = vdev_raidz_map_alloc_expanded(
87                                     zio_bench.io_abd,
88                                     zio_bench.io_size, zio_bench.io_offset,
89                                     rto_opts.rto_ashift, ncols+1, ncols,
90                                     fn+1, rto_opts.rto_expand_offset);
91                         } else {
92                                 rm_bench = vdev_raidz_map_alloc(&zio_bench,
93                                     BENCH_ASHIFT, ncols, fn+1);
94                         }
95
96                         /* estimate iteration count */
97                         iter_cnt = GEN_BENCH_MEMORY;
98                         iter_cnt /= zio_bench.io_size;
99
100                         start = gethrtime();
101                         for (iter = 0; iter < iter_cnt; iter++)
102                                 vdev_raidz_generate_parity(rm_bench);
103                         elapsed = NSEC2SEC((double)(gethrtime() - start));
104
105                         disksize = (1ULL << ds) / rto_opts.rto_dcols;
106                         d_bw = (double)iter_cnt * (double)disksize;
107                         d_bw /= (1024.0 * 1024.0 * elapsed);
108
109                         LOG(D_ALL, "%10s, %8s, %zu, %10llu, %lf, %lf, %u\n",
110                             impl,
111                             raidz_gen_name[fn],
112                             rto_opts.rto_dcols,
113                             (1ULL<<ds),
114                             d_bw,
115                             d_bw * (double)(ncols),
116                             (unsigned)iter_cnt);
117
118                         vdev_raidz_map_free(rm_bench);
119                 }
120         }
121 }
122
123 static void
124 run_gen_bench(void)
125 {
126         char **impl_name;
127
128         LOG(D_INFO, DBLSEP "\nBenchmarking parity generation...\n\n");
129         LOG(D_ALL, "impl, math, dcols, iosize, disk_bw, total_bw, iter\n");
130
131         for (impl_name = (char **)raidz_impl_names; *impl_name != NULL;
132             impl_name++) {
133
134                 if (vdev_raidz_impl_set(*impl_name) != 0)
135                         continue;
136
137                 run_gen_bench_impl(*impl_name);
138         }
139 }
140
141 static void
142 run_rec_bench_impl(const char *impl)
143 {
144         int fn, ncols, nbad;
145         uint64_t ds, iter_cnt, iter, disksize;
146         hrtime_t start;
147         double elapsed, d_bw;
148         static const int tgt[7][3] = {
149                 {1, 2, 3},      /* rec_p:   bad QR & D[0]       */
150                 {0, 2, 3},      /* rec_q:   bad PR & D[0]       */
151                 {0, 1, 3},      /* rec_r:   bad PQ & D[0]       */
152                 {2, 3, 4},      /* rec_pq:  bad R  & D[0][1]    */
153                 {1, 3, 4},      /* rec_pr:  bad Q  & D[0][1]    */
154                 {0, 3, 4},      /* rec_qr:  bad P  & D[0][1]    */
155                 {3, 4, 5}       /* rec_pqr: bad    & D[0][1][2] */
156         };
157
158         for (fn = 0; fn < RAIDZ_REC_NUM; fn++) {
159                 for (ds = MIN_CS_SHIFT; ds <= MAX_CS_SHIFT; ds++) {
160
161                         /* create suitable raidz_map */
162                         ncols = rto_opts.rto_dcols + PARITY_PQR;
163                         zio_bench.io_size = 1ULL << ds;
164
165                         /*
166                          * raidz block is too short to test
167                          * the requested method
168                          */
169                         if (zio_bench.io_size / rto_opts.rto_dcols <
170                             (1ULL << BENCH_ASHIFT))
171                                 continue;
172
173                         if (rto_opts.rto_expand) {
174                                 rm_bench = vdev_raidz_map_alloc_expanded(
175                                     zio_bench.io_abd,
176                                     zio_bench.io_size, zio_bench.io_offset,
177                                     BENCH_ASHIFT, ncols+1, ncols,
178                                     PARITY_PQR, rto_opts.rto_expand_offset);
179                         } else {
180                                 rm_bench = vdev_raidz_map_alloc(&zio_bench,
181                                     BENCH_ASHIFT, ncols, PARITY_PQR);
182                         }
183
184                         /* estimate iteration count */
185                         iter_cnt = (REC_BENCH_MEMORY);
186                         iter_cnt /= zio_bench.io_size;
187
188                         /* calculate how many bad columns there are */
189                         nbad = MIN(3, raidz_ncols(rm_bench) -
190                             raidz_parity(rm_bench));
191
192                         start = gethrtime();
193                         for (iter = 0; iter < iter_cnt; iter++)
194                                 vdev_raidz_reconstruct(rm_bench, tgt[fn], nbad);
195                         elapsed = NSEC2SEC((double)(gethrtime() - start));
196
197                         disksize = (1ULL << ds) / rto_opts.rto_dcols;
198                         d_bw = (double)iter_cnt * (double)(disksize);
199                         d_bw /= (1024.0 * 1024.0 * elapsed);
200
201                         LOG(D_ALL, "%10s, %8s, %zu, %10llu, %lf, %lf, %u\n",
202                             impl,
203                             raidz_rec_name[fn],
204                             rto_opts.rto_dcols,
205                             (1ULL<<ds),
206                             d_bw,
207                             d_bw * (double)ncols,
208                             (unsigned)iter_cnt);
209
210                         vdev_raidz_map_free(rm_bench);
211                 }
212         }
213 }
214
215 static void
216 run_rec_bench(void)
217 {
218         char **impl_name;
219
220         LOG(D_INFO, DBLSEP "\nBenchmarking data reconstruction...\n\n");
221         LOG(D_ALL, "impl, math, dcols, iosize, disk_bw, total_bw, iter\n");
222
223         for (impl_name = (char **)raidz_impl_names; *impl_name != NULL;
224             impl_name++) {
225
226                 if (vdev_raidz_impl_set(*impl_name) != 0)
227                         continue;
228
229                 run_rec_bench_impl(*impl_name);
230         }
231 }
232
233 void
234 run_raidz_benchmark(void)
235 {
236         bench_init_raidz_map();
237
238         run_gen_bench();
239         run_rec_bench();
240
241         bench_fini_raidz_maps();
242 }