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 <[email protected]>
*
* Author: Loic Dachary <[email protected]>
*
* 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: