RE: CEPH Erasure Encoding + OSD Scalability

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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:

[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux