Path: blob/main/sys/contrib/openzfs/cmd/raidz_test/raidz_bench.c
48380 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* 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.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright (C) 2016 Gvozden Nešković. All rights reserved.24*/2526#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>3334#include "raidz_test.h"3536#define GEN_BENCH_MEMORY (((uint64_t)1ULL)<<32)37#define REC_BENCH_MEMORY (((uint64_t)1ULL)<<29)38#define BENCH_ASHIFT 1239#define MIN_CS_SHIFT BENCH_ASHIFT40#define MAX_CS_SHIFT SPA_MAXBLOCKSHIFT4142static zio_t zio_bench;43static raidz_map_t *rm_bench;44static size_t max_data_size = SPA_MAXBLOCKSIZE;4546static void47bench_init_raidz_map(void)48{49zio_bench.io_offset = 0;50zio_bench.io_size = max_data_size;5152/*53* To permit larger column sizes these have to be done54* allocated using aligned alloc instead of zio_abd_buf_alloc55*/56zio_bench.io_abd = raidz_alloc(max_data_size);5758init_zio_abd(&zio_bench);59}6061static void62bench_fini_raidz_maps(void)63{64/* tear down golden zio */65raidz_free(zio_bench.io_abd, max_data_size);66memset(&zio_bench, 0, sizeof (zio_t));67}6869static inline void70run_gen_bench_impl(const char *impl)71{72int fn, ncols;73uint64_t ds, iter_cnt, iter, disksize;74hrtime_t start;75double elapsed, d_bw;7677/* Benchmark generate functions */78for (fn = 0; fn < RAIDZ_GEN_NUM; fn++) {7980for (ds = MIN_CS_SHIFT; ds <= MAX_CS_SHIFT; ds++) {81/* create suitable raidz_map */82ncols = rto_opts.rto_dcols + fn + 1;83zio_bench.io_size = 1ULL << ds;8485if (rto_opts.rto_expand) {86rm_bench = vdev_raidz_map_alloc_expanded(87&zio_bench,88rto_opts.rto_ashift, ncols+1, ncols,89fn+1, rto_opts.rto_expand_offset,900, B_FALSE);91} else {92rm_bench = vdev_raidz_map_alloc(&zio_bench,93BENCH_ASHIFT, ncols, fn+1);94}9596/* estimate iteration count */97iter_cnt = GEN_BENCH_MEMORY;98iter_cnt /= zio_bench.io_size;99100start = gethrtime();101for (iter = 0; iter < iter_cnt; iter++)102vdev_raidz_generate_parity(rm_bench);103elapsed = NSEC2SEC((double)(gethrtime() - start));104105disksize = (1ULL << ds) / rto_opts.rto_dcols;106d_bw = (double)iter_cnt * (double)disksize;107d_bw /= (1024.0 * 1024.0 * elapsed);108109LOG(D_ALL, "%10s, %8s, %zu, %10llu, %lf, %lf, %u\n",110impl,111raidz_gen_name[fn],112rto_opts.rto_dcols,113(1ULL<<ds),114d_bw,115d_bw * (double)(ncols),116(unsigned)iter_cnt);117118vdev_raidz_map_free(rm_bench);119}120}121}122123static void124run_gen_bench(void)125{126char **impl_name;127128LOG(D_INFO, DBLSEP "\nBenchmarking parity generation...\n\n");129LOG(D_ALL, "impl, math, dcols, iosize, disk_bw, total_bw, iter\n");130131for (impl_name = (char **)raidz_impl_names; *impl_name != NULL;132impl_name++) {133134if (vdev_raidz_impl_set(*impl_name) != 0)135continue;136137run_gen_bench_impl(*impl_name);138}139}140141static void142run_rec_bench_impl(const char *impl)143{144int fn, ncols, nbad;145uint64_t ds, iter_cnt, iter, disksize;146hrtime_t start;147double elapsed, d_bw;148static 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};157158for (fn = 0; fn < RAIDZ_REC_NUM; fn++) {159for (ds = MIN_CS_SHIFT; ds <= MAX_CS_SHIFT; ds++) {160161/* create suitable raidz_map */162ncols = rto_opts.rto_dcols + PARITY_PQR;163zio_bench.io_size = 1ULL << ds;164165/*166* raidz block is too short to test167* the requested method168*/169if (zio_bench.io_size / rto_opts.rto_dcols <170(1ULL << BENCH_ASHIFT))171continue;172173if (rto_opts.rto_expand) {174rm_bench = vdev_raidz_map_alloc_expanded(175&zio_bench,176BENCH_ASHIFT, ncols+1, ncols,177PARITY_PQR,178rto_opts.rto_expand_offset, 0, B_FALSE);179} else {180rm_bench = vdev_raidz_map_alloc(&zio_bench,181BENCH_ASHIFT, ncols, PARITY_PQR);182}183184/* estimate iteration count */185iter_cnt = (REC_BENCH_MEMORY);186iter_cnt /= zio_bench.io_size;187188/* calculate how many bad columns there are */189nbad = MIN(3, raidz_ncols(rm_bench) -190raidz_parity(rm_bench));191192start = gethrtime();193for (iter = 0; iter < iter_cnt; iter++)194vdev_raidz_reconstruct(rm_bench, tgt[fn], nbad);195elapsed = NSEC2SEC((double)(gethrtime() - start));196197disksize = (1ULL << ds) / rto_opts.rto_dcols;198d_bw = (double)iter_cnt * (double)(disksize);199d_bw /= (1024.0 * 1024.0 * elapsed);200201LOG(D_ALL, "%10s, %8s, %zu, %10llu, %lf, %lf, %u\n",202impl,203raidz_rec_name[fn],204rto_opts.rto_dcols,205(1ULL<<ds),206d_bw,207d_bw * (double)ncols,208(unsigned)iter_cnt);209210vdev_raidz_map_free(rm_bench);211}212}213}214215static void216run_rec_bench(void)217{218char **impl_name;219220LOG(D_INFO, DBLSEP "\nBenchmarking data reconstruction...\n\n");221LOG(D_ALL, "impl, math, dcols, iosize, disk_bw, total_bw, iter\n");222223for (impl_name = (char **)raidz_impl_names; *impl_name != NULL;224impl_name++) {225226if (vdev_raidz_impl_set(*impl_name) != 0)227continue;228229run_rec_bench_impl(*impl_name);230}231}232233void234run_raidz_benchmark(void)235{236bench_init_raidz_map();237238run_gen_bench();239run_rec_bench();240241bench_fini_raidz_maps();242}243244245