Просмотр исходного кода

csync_rename: optimize lookup

Avoid many memory allocations in reconcile
Olivier Goffart 8 лет назад
Родитель
Сommit
6583ebdcd9
3 измененных файлов с 24 добавлено и 15 удалено
  1. 14 9
      src/csync/csync_private.h
  2. 1 1
      src/csync/csync_reconcile.cpp
  3. 9 5
      src/csync/csync_rename.cpp

+ 14 - 9
src/csync/csync_private.h

@@ -81,29 +81,34 @@ class ByteArrayRef
     int _begin = 0;
     int _size = -1;
 
+    /* Pointer to the beginning of the data. WARNING: not null terminated */
+    const char *data() const { return _arr.constData() + _begin; }
+    friend struct ByteArrayRefHash;
+
 public:
-    ByteArrayRef(const QByteArray &arr = {}, int begin = 0, int size = -1)
-        : _arr(arr)
+    ByteArrayRef(QByteArray arr = {}, int begin = 0, int size = -1)
+        : _arr(std::move(arr))
         , _begin(begin)
-        , _size(qMin(arr.size() - begin, size < 0 ? arr.size() : size))
+        , _size(qMin(_arr.size() - begin, size < 0 ? _arr.size() - begin : size))
     {
     }
     ByteArrayRef left(int l) const { return ByteArrayRef(_arr, _begin, l); };
     char at(int x) const { return _arr.at(_begin + x); }
     int size() const { return _size; }
-    /* Pointer to the beginning of the data. WARNING: not null terminated */
-    const char *data() const { return _arr.constData() + _begin; }
+    int length() const { return _size; }
+    bool isEmpty() const { return _size == 0; }
 
     friend bool operator==(const ByteArrayRef &a, const ByteArrayRef &b)
     { return a.size() == b.size() && qstrncmp(a.data(), b.data(), a.size()) == 0; }
 };
+struct ByteArrayRefHash { uint operator()(const ByteArrayRef &a) const { return qHashBits(a.data(), a.size()); } };
 
 /**
  * @brief csync public structure
  */
 struct OCSYNC_EXPORT csync_s {
-  struct FileMapHash { uint operator()(const ByteArrayRef &a) const { return qHashBits(a.data(), a.size()); } };
-  class FileMap : public std::unordered_map<ByteArrayRef, std::unique_ptr<csync_file_stat_t>, FileMapHash> {
+
+  class FileMap : public std::unordered_map<ByteArrayRef, std::unique_ptr<csync_file_stat_t>, ByteArrayRefHash> {
   public:
       csync_file_stat_t *findFile(const ByteArrayRef &key) const {
           auto it = find(key);
@@ -137,8 +142,8 @@ struct OCSYNC_EXPORT csync_s {
   OCC::SyncJournalDb *statedb;
 
   struct {
-    std::map<QByteArray, QByteArray> folder_renamed_to; // map from->to
-    std::map<QByteArray, QByteArray> folder_renamed_from; // map to->from
+    std::unordered_map<ByteArrayRef, QByteArray, ByteArrayRefHash> folder_renamed_to; // map from->to
+    std::unordered_map<ByteArrayRef, QByteArray, ByteArrayRefHash> folder_renamed_from; // map to->from
   } renames;
 
   struct {

+ 1 - 1
src/csync/csync_reconcile.cpp

@@ -47,7 +47,7 @@ static csync_file_stat_t *_csync_check_ignored(csync_s::FileMap *tree, const Byt
     if (parentlen <= 0) {
         return nullptr;
     }
-    auto parentPath = path.left(parentlen);
+    ByteArrayRef parentPath = path.left(parentlen);
     csync_file_stat_t *fs = tree->findFile(parentPath);
     if (fs) {
         if (fs->instruction == CSYNC_INSTRUCTION_IGNORE) {

+ 9 - 5
src/csync/csync_rename.cpp

@@ -23,7 +23,7 @@
 
 #include <algorithm>
 
-static QByteArray _parentDir(const QByteArray &path) {
+static ByteArrayRef _parentDir(const ByteArrayRef &path) {
     int len = path.length();
     while(len > 0 && path.at(len-1)!='/') len--;
     while(len > 0 && path.at(len-1)=='/') len--;
@@ -38,8 +38,10 @@ void csync_rename_record(CSYNC* ctx, const QByteArray &from, const QByteArray &t
 
 QByteArray csync_rename_adjust_path(CSYNC* ctx, const QByteArray &path)
 {
-    for (QByteArray p = _parentDir(path); !p.isEmpty(); p = _parentDir(p)) {
-        std::map< QByteArray, QByteArray >::iterator it = ctx->renames.folder_renamed_to.find(p);
+    if (ctx->renames.folder_renamed_to.empty())
+        return path;
+    for (auto p = _parentDir(path); !p.isEmpty(); p = _parentDir(p)) {
+        auto it = ctx->renames.folder_renamed_to.find(p);
         if (it != ctx->renames.folder_renamed_to.end()) {
             QByteArray rep = it->second + path.mid(p.length());
             return rep;
@@ -50,8 +52,10 @@ QByteArray csync_rename_adjust_path(CSYNC* ctx, const QByteArray &path)
 
 QByteArray csync_rename_adjust_path_source(CSYNC* ctx, const QByteArray &path)
 {
-    for (QByteArray p = _parentDir(path); !p.isEmpty(); p = _parentDir(p)) {
-        std::map< QByteArray, QByteArray >::iterator it = ctx->renames.folder_renamed_from.find(p);
+    if (ctx->renames.folder_renamed_from.empty())
+        return path;
+    for (auto p = _parentDir(path); !p.isEmpty(); p = _parentDir(p)) {
+        auto it = ctx->renames.folder_renamed_from.find(p);
         if (it != ctx->renames.folder_renamed_from.end()) {
             QByteArray rep = it->second + path.mid(p.length());
             return rep;