From 2d7adb23bc52e7c0753f4571fecd8eefa209ef02 Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Thu, 25 Sep 2014 14:46:07 +0200 Subject: [PATCH] erasure-code: erasure_code_benchmark exhaustive erasure exploration Add the --erasure-generation exhaustive flag to try all combinations of erasures, not just one at random. Signed-off-by: Loic Dachary --- .../ceph_erasure_code_benchmark.cc | 104 +++++++++++++++--- .../ceph_erasure_code_benchmark.h | 8 ++ 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/test/erasure-code/ceph_erasure_code_benchmark.cc b/src/test/erasure-code/ceph_erasure_code_benchmark.cc index a9f5cf6966bc..cd1139feb411 100644 --- a/src/test/erasure-code/ceph_erasure_code_benchmark.cc +++ b/src/test/erasure-code/ceph_erasure_code_benchmark.cc @@ -4,6 +4,7 @@ * Ceph distributed storage system * * Copyright (C) 2013,2014 Cloudwatt + * Copyright (C) 2014 Red Hat * * Author: Loic Dachary * @@ -23,7 +24,6 @@ #include #include -#include "ceph_erasure_code_benchmark.h" #include "global/global_context.h" #include "global/global_init.h" #include "common/ceph_argparse.h" @@ -32,6 +32,7 @@ #include "include/utime.h" #include "erasure-code/ErasureCodePlugin.h" #include "erasure-code/ErasureCode.h" +#include "ceph_erasure_code_benchmark.h" namespace po = boost::program_options; @@ -51,6 +52,11 @@ int ErasureCodeBench::setup(int argc, char** argv) { "run either encode or decode") ("erasures,e", po::value()->default_value(1), "number of erasures when decoding") + ("erasures-generation,E", po::value()->default_value("random"), + "If set to 'random', pick the number of chunks to recover (as specified by " + " --erasures) at random. If set to 'exhaustive' try all combinations of erasures " + " (i.e. k=4,m=3 with one erasure will try to recover from the erasure of " + " the first chunk, then the second etc.)") ("parameter,P", po::value >(), "parameters") ; @@ -108,6 +114,11 @@ int ErasureCodeBench::setup(int argc, char** argv) { plugin = vm["plugin"].as(); workload = vm["workload"].as(); erasures = vm["erasures"].as(); + if (vm.count("erasures-generation") > 0 && + vm["erasures-generation"].as() == "exhaustive") + exhaustive_erasures = true; + else + exhaustive_erasures = false; k = atoi(parameters["k"].c_str()); m = atoi(parameters["m"].c_str()); @@ -174,6 +185,66 @@ int ErasureCodeBench::encode() return 0; } +int ErasureCodeBench::decode_erasures(const map &all_chunks, + const map &chunks, + unsigned i, + unsigned want_erasures, + ErasureCodeInterfaceRef erasure_code) +{ + int code = 0; + + if (want_erasures <= 0) { + if (verbose) + cout << "chunks "; + set want_to_read; + for (unsigned int chunk = 0; chunk < erasure_code->get_chunk_count(); chunk++) { + if (chunks.count(chunk) == 0) { + if (verbose) + cout << "(" << chunk << ")"; + want_to_read.insert(chunk); + } else { + if (verbose) + cout << " " << chunk << " "; + } + if (verbose) + cout << " "; + } + if (verbose) + cout << "(X) is an erased chunk" << endl; + + map decoded; + code = erasure_code->decode(want_to_read, chunks, &decoded); + if (code) + return code; + for (set::iterator chunk = want_to_read.begin(); + chunk != want_to_read.end(); + chunk++) { + if (all_chunks.find(*chunk)->second.length() != decoded[*chunk].length()) { + cerr << "chunk " << *chunk << " length=" << all_chunks.find(*chunk)->second.length() + << " decoded with length=" << decoded[*chunk].length() << endl; + return -1; + } + bufferlist tmp = all_chunks.find(*chunk)->second; + if (!tmp.contents_equal(decoded[*chunk])) { + cerr << "chunk " << *chunk + << " content and recovered content are different" << endl; + return -1; + } + } + return 0; + } + + for (; i < erasure_code->get_chunk_count(); i++) { + map one_less = chunks; + one_less.erase(i); + code = decode_erasures(all_chunks, one_less, i + 1, want_erasures - 1, erasure_code); + if (code) + return code; + } + + return 0; +} + int ErasureCodeBench::decode() { ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance(); @@ -210,18 +281,24 @@ int ErasureCodeBench::decode() utime_t begin_time = ceph_clock_now(g_ceph_context); for (int i = 0; i < max_iterations; i++) { - map chunks = encoded; - for (int j = 0; j < erasures; j++) { - int erasure; - do { - erasure = rand() % ( k + m ); - } while(chunks.count(erasure) == 0); - chunks.erase(erasure); + if (exhaustive_erasures) { + code = decode_erasures(encoded, encoded, 0, erasures, erasure_code); + if (code) + return code; + } else { + map chunks = encoded; + for (int j = 0; j < erasures; j++) { + int erasure; + do { + erasure = rand() % ( k + m ); + } while(chunks.count(erasure) == 0); + chunks.erase(erasure); + } + map decoded; + code = erasure_code->decode(want_to_read, chunks, &decoded); + if (code) + return code; } - map decoded; - code = erasure_code->decode(want_to_read, chunks, &decoded); - if (code) - return code; } utime_t end_time = ceph_clock_now(g_ceph_context); cout << (end_time - begin_time) << "\t" << (max_iterations * (in_size / 1024)) << endl; @@ -243,8 +320,7 @@ int main(int argc, char** argv) { /* * Local Variables: - * compile-command: "cd ../.. ; make -j4 && - * make ceph_erasure_code_benchmark && + * compile-command: "cd ../.. ; make -j4 ceph_erasure_code_benchmark && * valgrind --tool=memcheck --leak-check=full \ * ./ceph_erasure_code_benchmark \ * --plugin jerasure \ diff --git a/src/test/erasure-code/ceph_erasure_code_benchmark.h b/src/test/erasure-code/ceph_erasure_code_benchmark.h index 197831bccdde..2786e25a83ec 100644 --- a/src/test/erasure-code/ceph_erasure_code_benchmark.h +++ b/src/test/erasure-code/ceph_erasure_code_benchmark.h @@ -4,6 +4,7 @@ * Ceph distributed storage system * * Copyright (C) 2013,2014 Cloudwatt + * Copyright (C) 2014 Red Hat * * Author: Loic Dachary * @@ -29,6 +30,8 @@ class ErasureCodeBench { int m; string plugin; + + bool exhaustive_erasures; string workload; map parameters; @@ -37,6 +40,11 @@ class ErasureCodeBench { public: int setup(int argc, char** argv); int run(); + int decode_erasures(const map &all_chunks, + const map &chunks, + unsigned i, + unsigned want_erasures, + ErasureCodeInterfaceRef erasure_code); int decode(); int encode(); }; -- 2.47.3