Hi Loic, I have modified the Jerasure unit test, to record the encoding & reconstruction performance and to store this value in the optional google-test xml outputfile. I have put (4,2) with a 4MB random object as default and one can pass a different object size via '--object-size=1000' (for 1G). It looks like this: ./unittest_erasure_code_jerasure --gtest_filter=*.* --log-to-stderr=true --gtest_output="xml:erasure.xml" --object-size=1000 Note: Google Test filter = *.* [==========] Running 8 tests from 8 test cases. [----------] Global test environment set-up. [----------] 1 test from ErasureCodeTest/0, where TypeParam = ErasureCodeJerasureReedSolomonVandermonde [ RUN ] ErasureCodeTest/0.encode_decode [ OK ] ErasureCodeTest/0.encode_decode (35231 ms) [----------] 1 test from ErasureCodeTest/0 (35231 ms total) [----------] 1 test from ErasureCodeTest/1, where TypeParam = ErasureCodeJerasureReedSolomonRAID6 [ RUN ] ErasureCodeTest/1.encode_decode [ OK ] ErasureCodeTest/1.encode_decode (35594 ms) [----------] 1 test from ErasureCodeTest/1 (35594 ms total) [----------] 1 test from ErasureCodeTest/2, where TypeParam = ErasureCodeJerasureCauchyOrig [ RUN ] ErasureCodeTest/2.encode_decode [ OK ] ErasureCodeTest/2.encode_decode (33009 ms) [----------] 1 test from ErasureCodeTest/2 (33010 ms total) [----------] 1 test from ErasureCodeTest/3, where TypeParam = ErasureCodeJerasureCauchyGood [ RUN ] ErasureCodeTest/3.encode_decode [ OK ] ErasureCodeTest/3.encode_decode (31917 ms) [----------] 1 test from ErasureCodeTest/3 (31920 ms total) [----------] 1 test from ErasureCodeTest/4, where TypeParam = ErasureCodeJerasureLiberation [ RUN ] ErasureCodeTest/4.encode_decode [ OK ] ErasureCodeTest/4.encode_decode (31801 ms) [----------] 1 test from ErasureCodeTest/4 (31801 ms total) [----------] 1 test from ErasureCodeTest/5, where TypeParam = ErasureCodeJerasureBlaumRoth [ RUN ] ErasureCodeTest/5.encode_decode [ OK ] ErasureCodeTest/5.encode_decode (31927 ms) [----------] 1 test from ErasureCodeTest/5 (31927 ms total) [----------] 1 test from ErasureCodeTest/6, where TypeParam = ErasureCodeJerasureLiber8tion [ RUN ] ErasureCodeTest/6.encode_decode [ OK ] ErasureCodeTest/6.encode_decode (31824 ms) [----------] 1 test from ErasureCodeTest/6 (31824 ms total) [----------] 1 test from ErasureCodeTiming [ RUN ] ErasureCodeTiming.PropertyOutput [ -TIMING- ] technique=blaum_roth speed [ encode ]=2.902 [GB/s] [ -TIMING- ] technique=blaum_roth speed [ reco ]=1.701 [GB/s] [ -TIMING- ] technique=cauchy_good speed [ encode ]=2.551 [GB/s] [ -TIMING- ] technique=cauchy_good speed [ reco ]=1.571 [GB/s] [ -TIMING- ] technique=cauchy_orig speed [ encode ]=1.401 [GB/s] [ -TIMING- ] technique=cauchy_orig speed [ reco ]=0.911 [GB/s] [ -TIMING- ] technique=liber8tion speed [ encode ]=2.861 [GB/s] [ -TIMING- ] technique=liber8tion speed [ reco ]=1.822 [GB/s] [ -TIMING- ] technique=liberation speed [ encode ]=2.863 [GB/s] [ -TIMING- ] technique=liberation speed [ reco ]=1.815 [GB/s] [ -TIMING- ] technique=reed_sol_r6_op speed [ encode ]=1.194 [GB/s] [ -TIMING- ] technique=reed_sol_r6_op speed [ reco ]=0.489 [GB/s] [ -TIMING- ] technique=reed_sol_van speed [ encode ]=0.600 [GB/s] [ -TIMING- ] technique=reed_sol_van speed [ reco ]=0.429 [GB/s] [ OK ] ErasureCodeTiming.PropertyOutput (0 ms) [----------] 1 test from ErasureCodeTiming (0 ms total) [----------] Global test environment tear-down [==========] 8 tests from 8 test cases ran. (231307 ms total) [ PASSED ] 8 tests. [----------] Global test environment tear-down [==========] 8 tests from 8 test cases ran. (31351 ms total) [ PASSED ] 8 tests. And the XML: <testsuite name="ErasureCodeTiming" tests="1" failures="0" disabled="0" errors="0" time="0"> <testcase name="PropertyOutput" status="run" time="0" classname="ErasureCodeTiming" jerasure::blaum_roth::encode="2902" jerasure::blaum_roth::reco="1700" jerasure::cauchy_good::encode="2551" jerasure::cauchy_good::reco="1571" jerasure::cauchy_orig::encode="1401" jerasure::cauchy_orig::reco="910" jerasure::liber8tion::encode="2861" jerasure::liber8tion::reco="1821" jerasure::liberation::encode="2862" jerasure::liberation::reco="1814" jerasure::reed_sol_r6_op::encode="1194" jerasure::reed_sol_r6_op::reco="489" jerasure::reed_sol_van::encode="599" jerasure::reed_sol_van::reco="428" object-size="1000000000" /> </testsuite> Maybe you could use this directly for QA. Cheers Andreas.
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* * Ceph - scalable distributed file system * * Copyright (C) 2013 Cloudwatt <libre.licensing@xxxxxxxxxxxxx> * * Author: Loic Dachary <loic@xxxxxxxxxxx> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * */ #include "global/global_init.h" #include "osd/ErasureCodePluginJerasure/ErasureCodeJerasure.h" #include "common/ceph_argparse.h" #include "common/Clock.h" #include "common/ceph_context.h" #include "global/global_context.h" #include "gtest/gtest.h" typedef std::map<std::string,utime_t> timing_t; typedef std::map<std::string,timing_t > timing_map_t; timing_map_t timing; unsigned object_size = 4*1000*1000ll; template <typename T> class ErasureCodeTest : public ::testing::Test { public: }; typedef ::testing::Types< ErasureCodeJerasureReedSolomonVandermonde, ErasureCodeJerasureReedSolomonRAID6, ErasureCodeJerasureCauchyOrig, ErasureCodeJerasureCauchyGood, ErasureCodeJerasureLiberation, ErasureCodeJerasureBlaumRoth, ErasureCodeJerasureLiber8tion > JerasureTypes; TYPED_TEST_CASE(ErasureCodeTest, JerasureTypes); TYPED_TEST(ErasureCodeTest, encode_decode) { TypeParam jerasure; map<std::string,std::string> parameters; parameters["erasure-code-k"] = "4"; parameters["erasure-code-m"] = "2"; if ( ((std::string(jerasure.technique)=="liberation")) || ((std::string(jerasure.technique)=="blaum_roth")) ) parameters["erasure-code-w"] = "7"; else parameters["erasure-code-w"] = "8"; parameters["erasure-code-packetsize"] = "4096"; jerasure.init(parameters); #define LARGE_ENOUGH (7*object_size) bufferptr in_ptr(LARGE_ENOUGH); in_ptr.zero(); in_ptr.set_length(0); for (size_t i=0; i< object_size; i++) { char c = random(); in_ptr.append(&c,1); } bufferlist in; in.push_front(in_ptr); int want_to_encode[] = { 0, 1, 2, 3, 4, 5 }; map<int, bufferlist> encoded; timing[jerasure.technique]["encode-start"] = ceph_clock_now(0); EXPECT_EQ(0, jerasure.encode(set<int>(want_to_encode, want_to_encode+6), in, &encoded)); timing[jerasure.technique]["encode-stop"] = ceph_clock_now(0); EXPECT_EQ(6u, encoded.size()); unsigned length = encoded[0].length(); EXPECT_EQ(0, strncmp(encoded[0].c_str(), in.c_str(), length)); EXPECT_EQ(0, strncmp(encoded[1].c_str(), in.c_str() + length, in.length() - length)); // all chunks are available { int want_to_decode[] = { 0, 1 }; map<int, bufferlist> decoded; EXPECT_EQ(0, jerasure.decode(set<int>(want_to_decode, want_to_decode+2), encoded, &decoded)); // always decode all, regardless of want_to_decode EXPECT_EQ(6u, decoded.size()); EXPECT_EQ(length, decoded[0].length()); EXPECT_EQ(0, strncmp(decoded[0].c_str(), in.c_str(), length)); EXPECT_EQ(0, strncmp(decoded[1].c_str(), in.c_str() + length, in.length() - length)); } // two chunks are missing { map<int, bufferlist> degraded = encoded; degraded.erase(0); degraded.erase(1); EXPECT_EQ(4u, degraded.size()); int want_to_decode[] = { 0, 1 }; map<int, bufferlist> decoded; timing[jerasure.technique]["reco-start"] = ceph_clock_now(0); EXPECT_EQ(0, jerasure.decode(set<int>(want_to_decode, want_to_decode+2), degraded, &decoded)); timing[jerasure.technique]["reco-stop"] = ceph_clock_now(0); // always decode all, regardless of want_to_decode EXPECT_EQ(6u, decoded.size()); EXPECT_EQ(length, decoded[0].length()); EXPECT_EQ(0, strncmp(decoded[0].c_str(), in.c_str(), length)); EXPECT_EQ(0, strncmp(decoded[1].c_str(), in.c_str() + length, in.length() - length)); } timing[jerasure.technique]["encode"] = timing[jerasure.technique]["encode-stop"]-timing[jerasure.technique]["encode-start"]; timing[jerasure.technique]["reco"] = timing[jerasure.technique]["reco-stop"]-timing[jerasure.technique]["reco-start"]; } class ErasureCodeTiming : public ::testing::Test { public: }; TEST_F(ErasureCodeTiming, PropertyOutput) { for (timing_map_t::const_iterator techniqueit=timing.begin(); techniqueit!=timing.end(); ++techniqueit) { for (timing_t::const_iterator modeit=techniqueit->second.begin(); modeit!=techniqueit->second.end(); ++modeit) { char timingout[4096]; if (modeit->first.find("-start") != std::string::npos) continue; if (modeit->first.find("-stop") != std::string::npos) continue; double speed = object_size/1000000l/((double)modeit->second)/1000.0; snprintf(timingout, sizeof(timingout)-1, "[ -TIMING- ] technique=%-16s speed [ %6s ]=%02.03f [GB/s]\n", techniqueit->first.c_str(), modeit->first.c_str(), speed); cout << timingout; std::string property= std::string("jerasure::") + techniqueit->first.c_str() + "::" + modeit->first.c_str(); RecordProperty(property.c_str(), speed *1000); } } RecordProperty("object-size", object_size); } int main(int argc, char **argv) { vector<const char*> args; argv_to_vec(argc, (const char **)argv, args); global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); common_init_finish(g_ceph_context); ::testing::InitGoogleTest(&argc, argv); for (int i=0; i< argc; i++) { std::string arg=argv[i]; if (arg.substr(0,14)=="--object-size=") { arg.erase(0,14); object_size = atoi(arg.c_str())*1000*1000ll; } if ( !object_size || (object_size > 2000000000ll) ) { fprintf(stderr,"error: --object-size=MB ==> ( 0 < MB <= 2000 )\n"); exit(EINVAL); } } return RUN_ALL_TESTS(); } // Local Variables: // compile-command: "cd ../.. ; make -j4 && make unittest_erasure_code_jerasure && valgrind --tool=memcheck ./unittest_erasure_code_jerasure --gtest_filter=*.* --log-to-stderr=true --debug-osd=20 [--object-size=4]" // End: