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