]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
erasure code: shec performance optimization with decoding cache 5257/head
authorTakanori Nakao <nakao.takanori@jp.fujitsu.com>
Fri, 10 Jul 2015 04:41:45 +0000 (13:41 +0900)
committerTakeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
Fri, 4 Sep 2015 08:24:36 +0000 (17:24 +0900)
continued from https://github.com/ceph/ceph/pull/4132

Signed-off-by: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
src/erasure-code/shec/ErasureCodeShec.cc
src/erasure-code/shec/ErasureCodeShecTableCache.cc
src/erasure-code/shec/ErasureCodeShecTableCache.h

index f02a9722682229495066c7258c70d25718f015c4..5dcaf44da125940d39214f6f997d8d5ae44fcdf6 100644 (file)
@@ -562,6 +562,14 @@ int ErasureCodeShec::shec_make_decoding_matrix(bool prepare, int *want_, int *av
     }
   }
 
+  if (tcache.getDecodingTableFromCache(decoding_matrix,
+                                       dm_row, dm_column, minimum,
+                                       technique,
+                                       k, m, c, w,
+                                       want, avails)) {
+    return 0;
+  }
+
   for (unsigned long long pp = 0; pp < (1ull << m); ++pp) {
 
     // select parity chunks
@@ -755,6 +763,9 @@ int ErasureCodeShec::shec_make_decoding_matrix(bool prepare, int *want_, int *av
 
   int ret = jerasure_invert_matrix(tmpmat, decoding_matrix, mindup, w);
 
+  tcache.putDecodingTableToCache(decoding_matrix, dm_row, dm_column, minimum, technique,
+                                 k, m, c, w, want, avails);
+
   return ret;
 }
 
index 8fb64b2519cb870ad57d7ae4cc14c416897ff566..a037892f67c092b89576fda6ae48be0c8353d74d 100644 (file)
 #include "common/debug.h"
 // -----------------------------------------------------------------------------
 
+// -----------------------------------------------------------------------------
+#define dout_subsys ceph_subsys_osd
+#undef dout_prefix
+#define dout_prefix _tc_prefix(_dout)
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+
+static ostream&
+_tc_prefix(std::ostream* _dout) {
+  return *_dout << "ErasureCodeShecTableCache: ";
+}
+
+// -----------------------------------------------------------------------------
+
 ErasureCodeShecTableCache::~ErasureCodeShecTableCache()
 {
   Mutex::Locker lock(codec_tables_guard);
 
-  codec_technique_tables_t::const_iterator ttables_it;
-  codec_tables_t::const_iterator tables_it;
-  codec_tables_t_::const_iterator tables_it_;
-  codec_tables_t__::const_iterator tables_it__;
-  codec_table_t::const_iterator table_it;
-
   // clean-up all allocated tables
+  {
+    codec_technique_tables_t::const_iterator ttables_it;
+    codec_tables_t::const_iterator tables_it;
+    codec_tables_t_::const_iterator tables_it_;
+    codec_tables_t__::const_iterator tables_it__;
+    codec_table_t::const_iterator table_it;
 
-  for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) {
-    for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
-      for (tables_it_ = tables_it->second.begin(); tables_it_ != tables_it->second.end(); ++tables_it_) {
-       for (tables_it__ = tables_it_->second.begin(); tables_it__ != tables_it_->second.end(); ++tables_it__) {
-         for (table_it = tables_it__->second.begin(); table_it != tables_it__->second.end(); ++table_it) {
-           if (table_it->second) {
-             if (*(table_it->second)) {
-               delete *(table_it->second);
-             }
-             delete table_it->second;
-           }
-         }
+    for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) {
+      for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
+        for (tables_it_ = tables_it->second.begin(); tables_it_ != tables_it->second.end(); ++tables_it_) {
+          for (tables_it__ = tables_it_->second.begin(); tables_it__ != tables_it_->second.end(); ++tables_it__) {
+            for (table_it = tables_it__->second.begin(); table_it != tables_it__->second.end(); ++table_it) {
+              if (table_it->second) {
+                if (*(table_it->second)) {
+                  delete *(table_it->second);
+                }
+                delete table_it->second;
+              }
+            }
+          }
         }
       }
     }
   }
+
+  {
+    std::map<int, lru_map_t*>::const_iterator lru_map_it;
+    std::map<int, lru_list_t*>::const_iterator lru_list_it;
+
+    for (lru_map_it = decoding_tables.begin();
+         lru_map_it != decoding_tables.end();
+         ++lru_map_it) {
+      if (lru_map_it->second) {
+        delete lru_map_it->second;
+      }
+    }
+
+    for (lru_list_it = decoding_tables_lru.begin();
+         lru_list_it != decoding_tables_lru.end();
+         ++lru_list_it) {
+      if (lru_list_it->second) {
+        delete lru_list_it->second;
+      }
+    }
+  }
+}
+
+ErasureCodeShecTableCache::lru_map_t*
+ErasureCodeShecTableCache::getDecodingTables(int technique) {
+  // the caller must hold the guard mutex:
+  // => Mutex::Locker lock(codec_tables_guard);
+
+  // create an lru_map if not yet allocated
+  if (!decoding_tables[technique]) {
+    decoding_tables[technique] = new lru_map_t;
+  }
+  return decoding_tables[technique];
+}
+
+ErasureCodeShecTableCache::lru_list_t*
+ErasureCodeShecTableCache::getDecodingTablesLru(int technique) {
+  // the caller must hold the guard mutex:
+  // => Mutex::Locker lock(codec_tables_guard);
+
+  // create an lru_list if not yet allocated
+  if (!decoding_tables_lru[technique]) {
+    decoding_tables_lru[technique] = new lru_list_t;
+  }
+  return decoding_tables_lru[technique];
 }
 
 int**
@@ -95,3 +156,162 @@ ErasureCodeShecTableCache::getLock()
 {
   return &codec_tables_guard;
 }
+
+uint64_t
+ErasureCodeShecTableCache::getDecodingCacheSignature(int k, int m, int c, int w,
+                                                     int *erased, int *avails) {
+  uint64_t signature = 0;
+  signature = (uint64_t)k;
+  signature |= ((uint64_t)m << 6);
+  signature |= ((uint64_t)c << 12);
+  signature |= ((uint64_t)w << 18);
+
+  for (int i=0; i < k+m; i++) {
+    signature |= ((uint64_t)(avails[i] ? 1 : 0) << (24+i));
+  }
+  for (int i=0; i < k+m; i++) {
+    signature |= ((uint64_t)(erased[i] ? 1 : 0) << (44+i));
+  }
+  return signature;
+}
+
+bool
+ErasureCodeShecTableCache::getDecodingTableFromCache(int* decoding_matrix,
+                                                     int* dm_row,
+                                                     int* dm_column,
+                                                     int* minimum,
+                                                     int technique,
+                                                     int k,
+                                                     int m,
+                                                     int c,
+                                                     int w,
+                                                     int* erased,
+                                                     int* avails) {
+  // --------------------------------------------------------------------------
+  // LRU decoding matrix cache
+  // --------------------------------------------------------------------------
+
+  uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
+  Mutex::Locker lock(codec_tables_guard);
+
+  dout(20) << "[ get table    ] = " << signature << dendl;
+
+  // we try to fetch a decoding table from an LRU cache
+  lru_map_t* decode_tbls_map =
+    getDecodingTables(technique);
+
+  lru_list_t* decode_tbls_lru =
+    getDecodingTablesLru(technique);
+
+  lru_map_t::iterator decode_tbls_map_it = decode_tbls_map->find(signature);
+  if (decode_tbls_map_it == decode_tbls_map->end()) {
+    return false;
+  }
+
+  dout(20) << "[ cached table ] = " << signature << dendl;
+  // copy parameters out of the cache
+
+  memcpy(decoding_matrix,
+         decode_tbls_map_it->second.second.decoding_matrix,
+         k * k * sizeof(int));
+  memcpy(dm_row,
+         decode_tbls_map_it->second.second.dm_row,
+         k * sizeof(int));
+  memcpy(dm_column,
+         decode_tbls_map_it->second.second.dm_column,
+         k * sizeof(int));
+  memcpy(minimum,
+         decode_tbls_map_it->second.second.minimum,
+         (k+m) * sizeof(int));
+
+  // find item in LRU queue and push back
+  decode_tbls_lru->splice(decode_tbls_lru->end(),
+                          *decode_tbls_lru,
+                          decode_tbls_map_it->second.first);
+  return true;
+}
+
+void
+ErasureCodeShecTableCache::putDecodingTableToCache(int* decoding_matrix,
+                                                   int* dm_row,
+                                                   int* dm_column,
+                                                   int* minimum,
+                                                   int technique,
+                                                   int k,
+                                                   int m,
+                                                   int c,
+                                                   int w,
+                                                   int* erased,
+                                                   int* avails) {
+  // --------------------------------------------------------------------------
+  // LRU decoding matrix cache
+  // --------------------------------------------------------------------------
+
+  Mutex::Locker lock(codec_tables_guard);
+
+  uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
+  dout(20) << "[ put table    ] = " << signature << dendl;
+
+  // we store a new table to the cache
+
+  //  bufferptr cachetable;
+
+  lru_map_t* decode_tbls_map =
+    getDecodingTables(technique);
+
+  lru_list_t* decode_tbls_lru =
+    getDecodingTablesLru(technique);
+
+  if (decode_tbls_map->count(signature)) {
+    dout(20) << "[ already on table ] = " << signature << dendl;
+
+    // find item in LRU queue and push back
+    decode_tbls_lru->splice(decode_tbls_lru->end(),
+                            *decode_tbls_lru,
+                            (*decode_tbls_map)[signature].first);
+    return;
+  }
+
+  // evt. shrink the LRU queue/map
+  if ((int)decode_tbls_lru->size() >=
+      ErasureCodeShecTableCache::decoding_tables_lru_length) {
+    dout(20) << "[ shrink lru   ] = " << signature << dendl;
+    // remove from map
+    decode_tbls_map->erase(decode_tbls_lru->front());
+    // remove from lru
+    decode_tbls_lru->pop_front();
+  }
+
+  {
+    dout(20) << "[ store table  ] = " << signature << dendl;
+
+    decode_tbls_lru->push_back(signature);
+
+    // allocate a new buffer
+    lru_list_t::iterator it_end = decode_tbls_lru->end();
+    it_end--;
+
+    lru_entry_t &map_value =
+      (*decode_tbls_map)[signature] =
+      std::make_pair(it_end, DecodingCacheParameter());
+    map_value.second.decoding_matrix = new int[k*k];
+    map_value.second.dm_row = new int[k];
+    map_value.second.dm_column = new int[k];
+    map_value.second.minimum = new int[k+m];
+
+    memcpy(map_value.second.decoding_matrix,
+           decoding_matrix,
+           k * k * sizeof(int));
+    memcpy(map_value.second.dm_row,
+           dm_row,
+           k * sizeof(int));
+    memcpy(map_value.second.dm_column,
+           dm_column,
+           k * sizeof(int));
+    memcpy(map_value.second.minimum,
+           minimum,
+           (k+m) * sizeof(int));
+
+    dout(20) << "[ cache size   ] = " << decode_tbls_lru->size() << dendl;
+  }
+}
index 21f65bdfa6ff0cf5b1641f4b3554f57b2d0cd41a..e4eaf0f0eaa3332098b366b1a9e594baf6240ed6 100644 (file)
@@ -31,11 +31,43 @@ class ErasureCodeShecTableCache {
   // ---------------------------------------------------------------------------
   // This class implements a table cache for encoding and decoding matrices.
   // Encoding matrices are shared for the same (k,m,c,w) combination.
+  // It supplies a decoding matrix lru cache which is shared for identical
+  // matrix types e.g. there is one cache (lru-list + lru-map)
   // ---------------------------------------------------------------------------
 
+  class DecodingCacheParameter {
+   public:
+    int* decoding_matrix;  // size: k*k
+    int* dm_row;  // size: k
+    int* dm_column;  // size: k
+    int* minimum;  // size: k+m
+    DecodingCacheParameter() {
+      decoding_matrix = 0;
+      dm_row = 0;
+      dm_column = 0;
+      minimum = 0;
+    }
+    ~DecodingCacheParameter() {
+      if (decoding_matrix) {
+        delete[] decoding_matrix;
+      }
+      if (dm_row) {
+        delete[] dm_row;
+      }
+      if (dm_column) {
+        delete[] dm_column;
+      }
+      if (minimum) {
+        delete[] minimum;
+      }
+    }
+  };
+
  public:
 
-  typedef std::pair<std::list<std::string>::iterator, bufferptr> lru_entry_t;
+  static const int decoding_tables_lru_length = 10000;
+  typedef std::pair<std::list<uint64_t>::iterator,
+                    DecodingCacheParameter> lru_entry_t;
   typedef std::map< int, int** > codec_table_t;
   typedef std::map< int, codec_table_t > codec_tables_t__;
   typedef std::map< int, codec_tables_t__ > codec_tables_t_;
@@ -43,6 +75,9 @@ class ErasureCodeShecTableCache {
   typedef std::map< int, codec_tables_t > codec_technique_tables_t;
   // int** matrix = codec_technique_tables_t[technique][k][m][c][w]
   
+  typedef std::map< uint64_t, lru_entry_t > lru_map_t;
+  typedef std::list< uint64_t > lru_list_t;
+
  ErasureCodeShecTableCache() :
   codec_tables_guard("shec-lru-cache")
     {
@@ -52,15 +87,38 @@ class ErasureCodeShecTableCache {
   
   Mutex codec_tables_guard; // mutex used to protect modifications in encoding/decoding table maps
   
+  bool getDecodingTableFromCache(int* matrix,
+                                 int* dm_row, int* dm_column,
+                                 int* minimum,
+                                 int technique,
+                                 int k, int m, int c, int w,
+                                 int* want, int* avails);
+
+  void putDecodingTableToCache(int* matrix,
+                               int* dm_row, int* dm_column,
+                               int* minimum,
+                               int technique,
+                               int k, int m, int c, int w,
+                               int* want, int* avails);
+
   int** getEncodingTable(int technique, int k, int m, int c, int w);
   int** getEncodingTableNoLock(int technique, int k, int m, int c, int w);
   int* setEncodingTable(int technique, int k, int m, int c, int w, int*);
   
  private:
-  codec_technique_tables_t encoding_table; // encoding coefficients accessed via table[technique][k][m]
-  
+  // encoding table accessed via table[matrix][k][m][c][w]
+  // decoding table cache accessed via map[matrixtype]
+  // decoding table lru list accessed via list[matrixtype]
+  codec_technique_tables_t encoding_table;
+  std::map<int, lru_map_t*> decoding_tables;
+  std::map<int, lru_list_t*> decoding_tables_lru;
+
+  lru_map_t* getDecodingTables(int technique);
+  lru_list_t* getDecodingTablesLru(int technique);
+  uint64_t getDecodingCacheSignature(int k, int m, int c, int w,
+                                     int *want, int *avails);
+
   Mutex* getLock();
-  
 };
 
 #endif