[PATCH] D32853: [ELF] - Speedup readAddressArea() implementation.

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu May 4 02:58:59 PDT 2017


grimar created this revision.
Herald added a subscriber: aprantl.

readAddressArea() implementation in part of searching inputsection
that range belongs to is ineffective. Implementation is O(N*M) where
N is number of input sections and M is number of ranges. Since
each input section may have own range, complexity can be quadratic.

Patch reimplements it using binary search.

For benchmark I used debug LLC binary built with -gsplit-dwarf and -ggnu-pubnames
Numbers are (20 runs for each):

1. Original LLD without --gdb-index link time is 1,644984654 seconds ( +-  0,28% )
2. LLD without patch + --gdb-index link time is 6,200055217 seconds ( +-  0,15% )
3. LLD with this patch + --gdb-index link time is 4,305998886 seconds ( +-  0,16% )

Time spent for building gdbindex changes from (6.2 - 1.644 == 4.556) to (4.305 - 1.644 == 2.664).
That is 2.664/4.556 = 0.584 or about 42% speedup.

I also tried different solution without use of additional vector, demo is available: https://reviews.llvm.org/D32851, but this
patch is faster and looks cleaner.


https://reviews.llvm.org/D32853

Files:
  ELF/SyntheticSections.cpp


Index: ELF/SyntheticSections.cpp
===================================================================
--- ELF/SyntheticSections.cpp
+++ ELF/SyntheticSections.cpp
@@ -1704,29 +1704,31 @@
   return Ret;
 }
 
-static InputSectionBase *findSection(ArrayRef<InputSectionBase *> Arr,
-                                     uint64_t Offset) {
-  for (InputSectionBase *S : Arr)
-    if (S && S != &InputSection::Discarded)
-      if (Offset >= S->getOffsetInFile() &&
-          Offset < S->getOffsetInFile() + S->getSize())
-        return S;
-  return nullptr;
-}
-
 static std::vector<AddressEntry>
 readAddressArea(DWARFContext &Dwarf, InputSection *Sec, size_t CurrentCU) {
   std::vector<AddressEntry> Ret;
 
+  std::vector<InputSectionBase *> V = Sec->File->getSections();
+  auto E = llvm::remove_if(V, [](InputSectionBase *IS) {
+    return !IS || IS == &InputSection::Discarded || !IS->getSize();
+  });
+  V.erase(E, V.end());
+
   for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units()) {
     DWARFAddressRangesVector Ranges;
     CU->collectAddressRanges(Ranges);
 
-    ArrayRef<InputSectionBase *> Sections = Sec->File->getSections();
-    for (std::pair<uint64_t, uint64_t> &R : Ranges)
-      if (InputSectionBase *S = findSection(Sections, R.first))
-        Ret.push_back({S, R.first - S->getOffsetInFile(),
-                       R.second - S->getOffsetInFile(), CurrentCU});
+    for (std::pair<uint64_t, uint64_t> &R : Ranges) {
+      auto I = std::lower_bound(V.begin(), V.end(), R.first,
+                                [](InputSectionBase *IS, uint64_t Offset) {
+                                  return IS->getOffsetInFile() < Offset;
+                                });
+      if (I == V.end())
+        continue;
+      InputSectionBase *IS = *I;
+      Ret.push_back({IS, R.first - IS->getOffsetInFile(),
+                     R.second - IS->getOffsetInFile(), CurrentCU});
+    }
     ++CurrentCU;
   }
   return Ret;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D32853.97798.patch
Type: text/x-patch
Size: 1957 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170504/615ffb79/attachment.bin>


More information about the llvm-commits mailing list