[clang] [Serialization] Don't read all declaration id eagerly when merge the tables (PR #95506)

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 13 22:34:54 PDT 2024


https://github.com/ChuanqiXu9 created https://github.com/llvm/llvm-project/pull/95506

See the post commit message in
https://github.com/llvm/llvm-project/pull/92083 for rationale.

Previously, when we merge the lookup tables, we will read the tables completely to get the data. But the above page shows that it might be problematic in specific cases where there a lot of DeclIDs to be read.

In this patch, we mitigated the problem by not reading the contents of the merged tables. But we may need to pay for the additional memory usages.

>From 5adb69ef86de078f2b6446a16501941dfbdf4f57 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
Date: Fri, 14 Jun 2024 13:05:05 +0800
Subject: [PATCH] [Serialization] Don't read all declaration id eagerly when
 merge the tables

See the post commit message in
https://github.com/llvm/llvm-project/pull/92083 for rationale.

Previously, when we merge the lookup tables, we will read the tables
completely to get the data. But the above page shows that it might be
problematic in specific cases where there a lot of DeclIDs to be read.

In this patch, we mitigated the problem by not reading the contents of
the merged tables. But we may need to pay for the additional memory
usages.
---
 .../lib/Serialization/MultiOnDiskHashTable.h  | 64 ++++++++++++++++---
 1 file changed, 54 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Serialization/MultiOnDiskHashTable.h b/clang/lib/Serialization/MultiOnDiskHashTable.h
index a0d75ec3a9e76..f98394e904549 100644
--- a/clang/lib/Serialization/MultiOnDiskHashTable.h
+++ b/clang/lib/Serialization/MultiOnDiskHashTable.h
@@ -73,6 +73,51 @@ template<typename Info> class MultiOnDiskHashTable {
   struct MergedTable {
     std::vector<file_type> Files;
     llvm::DenseMap<internal_key_type, data_type> Data;
+
+    struct UnreadDataInfo {
+      Info *InfoObj;
+      const unsigned char *start;
+      unsigned DataLen;
+    };
+
+    llvm::DenseMap<internal_key_type, llvm::SmallVector<UnreadDataInfo, 16>>
+        UnReadData;
+
+    std::vector<OnDiskTable *> MergedOnDiskTables;
+
+    void clear() {
+      for (OnDiskTable *ODT : MergedOnDiskTables)
+        delete ODT;
+
+      MergedOnDiskTables.clear();
+    }
+
+    void readAll() {
+      for (const auto &Iter : UnReadData) {
+        internal_key_type Key = Iter.first;
+        data_type_builder ValueBuilder(Data[Key]);
+
+        for (const UnreadDataInfo &I : Iter.second)
+          I.InfoObj->ReadDataInto(Key, I.start, I.DataLen, ValueBuilder);
+      }
+
+      UnReadData.clear();
+      clear();
+    }
+
+    data_type find(internal_key_type Key) {
+      auto UnreadIter = UnReadData.find(Key);
+      if (UnreadIter != UnReadData.end()) {
+        data_type_builder ValueBuilder(Data[Key]);
+        for (auto &I : UnreadIter->second)
+          I.InfoObj->ReadDataInto(Key, I.start, I.DataLen, ValueBuilder);
+        UnReadData.erase(UnreadIter);
+      }
+
+      return Data[Key];
+    }
+
+    ~MergedTable() { clear(); }
   };
 
   using Table = llvm::PointerUnion<OnDiskTable *, MergedTable *>;
@@ -159,13 +204,14 @@ template<typename Info> class MultiOnDiskHashTable {
         // FIXME: Don't rely on the OnDiskHashTable format here.
         auto L = InfoObj.ReadKeyDataLength(LocalPtr);
         const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first);
-        data_type_builder ValueBuilder(Merged->Data[Key]);
-        InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second,
-                             ValueBuilder);
+        // Make sure Merged->Data contains every key.
+        (void)Merged->Data[Key];
+        Merged->UnReadData[Key].push_back(
+            {&InfoObj, LocalPtr + L.first, L.second});
       }
 
       Merged->Files.push_back(ODT->File);
-      delete ODT;
+      Merged->MergedOnDiskTables.push_back(ODT);
     }
 
     Tables.clear();
@@ -239,11 +285,8 @@ template<typename Info> class MultiOnDiskHashTable {
     internal_key_type Key = Info::GetInternalKey(EKey);
     auto KeyHash = Info::ComputeHash(Key);
 
-    if (MergedTable *M = getMergedTable()) {
-      auto It = M->Data.find(Key);
-      if (It != M->Data.end())
-        Result = It->second;
-    }
+    if (MergedTable *M = getMergedTable())
+      Result = M->find(Key);
 
     data_type_builder ResultBuilder(Result);
 
@@ -268,6 +311,7 @@ template<typename Info> class MultiOnDiskHashTable {
       removeOverriddenTables();
 
     if (MergedTable *M = getMergedTable()) {
+      M->readAll();
       for (auto &KV : M->Data)
         Info::MergeDataInto(KV.second, ResultBuilder);
     }
@@ -327,7 +371,7 @@ class MultiOnDiskHashTableGenerator {
         // Add all merged entries from Base to the generator.
         for (auto &KV : Merged->Data) {
           if (!Gen.contains(KV.first, Info))
-            Gen.insert(KV.first, Info.ImportData(KV.second), Info);
+            Gen.insert(KV.first, Info.ImportData(Merged->find(KV.first)), Info);
         }
       } else {
         Writer.write<uint32_t>(0);



More information about the cfe-commits mailing list