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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
23 * Copyright (C) 2016 Gvozden Nešković. All rights reserved.
26 #include <sys/zfs_context.h>
30 #include <sys/vdev_raidz.h>
31 #include <sys/vdev_raidz_impl.h>
34 #include "raidz_test.h"
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
42 static zio_t zio_bench
;
43 static raidz_map_t
*rm_bench
;
44 static size_t max_data_size
= SPA_MAXBLOCKSIZE
;
47 bench_init_raidz_map(void)
49 zio_bench
.io_offset
= 0;
50 zio_bench
.io_size
= max_data_size
;
53 * To permit larger column sizes these have to be done
54 * allocated using aligned alloc instead of zio_abd_buf_alloc
56 zio_bench
.io_abd
= raidz_alloc(max_data_size
);
58 init_zio_abd(&zio_bench
);
62 bench_fini_raidz_maps(void)
64 /* tear down golden zio */
65 raidz_free(zio_bench
.io_abd
, max_data_size
);
66 memset(&zio_bench
, 0, sizeof (zio_t
));
70 run_gen_bench_impl(const char *impl
)
73 uint64_t ds
, iter_cnt
, iter
, disksize
;
77 /* Benchmark generate functions */
78 for (fn
= 0; fn
< RAIDZ_GEN_NUM
; fn
++) {
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
;
85 if (rto_opts
.rto_expand
) {
86 rm_bench
= vdev_raidz_map_alloc_expanded(
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
);
92 rm_bench
= vdev_raidz_map_alloc(&zio_bench
,
93 BENCH_ASHIFT
, ncols
, fn
+1);
96 /* estimate iteration count */
97 iter_cnt
= GEN_BENCH_MEMORY
;
98 iter_cnt
/= zio_bench
.io_size
;
101 for (iter
= 0; iter
< iter_cnt
; iter
++)
102 vdev_raidz_generate_parity(rm_bench
);
103 elapsed
= NSEC2SEC((double)(gethrtime() - start
));
105 disksize
= (1ULL << ds
) / rto_opts
.rto_dcols
;
106 d_bw
= (double)iter_cnt
* (double)disksize
;
107 d_bw
/= (1024.0 * 1024.0 * elapsed
);
109 LOG(D_ALL
, "%10s, %8s, %zu, %10llu, %lf, %lf, %u\n",
115 d_bw
* (double)(ncols
),
118 vdev_raidz_map_free(rm_bench
);
128 LOG(D_INFO
, DBLSEP
"\nBenchmarking parity generation...\n\n");
129 LOG(D_ALL
, "impl, math, dcols, iosize, disk_bw, total_bw, iter\n");
131 for (impl_name
= (char **)raidz_impl_names
; *impl_name
!= NULL
;
134 if (vdev_raidz_impl_set(*impl_name
) != 0)
137 run_gen_bench_impl(*impl_name
);
142 run_rec_bench_impl(const char *impl
)
145 uint64_t ds
, iter_cnt
, iter
, disksize
;
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] */
158 for (fn
= 0; fn
< RAIDZ_REC_NUM
; fn
++) {
159 for (ds
= MIN_CS_SHIFT
; ds
<= MAX_CS_SHIFT
; ds
++) {
161 /* create suitable raidz_map */
162 ncols
= rto_opts
.rto_dcols
+ PARITY_PQR
;
163 zio_bench
.io_size
= 1ULL << ds
;
166 * raidz block is too short to test
167 * the requested method
169 if (zio_bench
.io_size
/ rto_opts
.rto_dcols
<
170 (1ULL << BENCH_ASHIFT
))
173 if (rto_opts
.rto_expand
) {
174 rm_bench
= vdev_raidz_map_alloc_expanded(
176 zio_bench
.io_size
, zio_bench
.io_offset
,
177 BENCH_ASHIFT
, ncols
+1, ncols
,
178 PARITY_PQR
, rto_opts
.rto_expand_offset
);
180 rm_bench
= vdev_raidz_map_alloc(&zio_bench
,
181 BENCH_ASHIFT
, ncols
, PARITY_PQR
);
184 /* estimate iteration count */
185 iter_cnt
= (REC_BENCH_MEMORY
);
186 iter_cnt
/= zio_bench
.io_size
;
188 /* calculate how many bad columns there are */
189 nbad
= MIN(3, raidz_ncols(rm_bench
) -
190 raidz_parity(rm_bench
));
193 for (iter
= 0; iter
< iter_cnt
; iter
++)
194 vdev_raidz_reconstruct(rm_bench
, tgt
[fn
], nbad
);
195 elapsed
= NSEC2SEC((double)(gethrtime() - start
));
197 disksize
= (1ULL << ds
) / rto_opts
.rto_dcols
;
198 d_bw
= (double)iter_cnt
* (double)(disksize
);
199 d_bw
/= (1024.0 * 1024.0 * elapsed
);
201 LOG(D_ALL
, "%10s, %8s, %zu, %10llu, %lf, %lf, %u\n",
207 d_bw
* (double)ncols
,
210 vdev_raidz_map_free(rm_bench
);
220 LOG(D_INFO
, DBLSEP
"\nBenchmarking data reconstruction...\n\n");
221 LOG(D_ALL
, "impl, math, dcols, iosize, disk_bw, total_bw, iter\n");
223 for (impl_name
= (char **)raidz_impl_names
; *impl_name
!= NULL
;
226 if (vdev_raidz_impl_set(*impl_name
) != 0)
229 run_rec_bench_impl(*impl_name
);
234 run_raidz_benchmark(void)
236 bench_init_raidz_map();
241 bench_fini_raidz_maps();