[PATCH] D36941: ms-pdb: Precompute deserialized symbols for pdb once and then use it in sort instead of doing it in the comparison function

Alex Telishev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 20 13:49:04 PDT 2017


alex.telishev created this revision.
Herald added a subscriber: hiraditya.

`computeAddrMap` function calls `std::stable_sort` with a comparison function that computes deserialized symbols every time its called. In the result `deserializeAs<PublicSym32>` is called 20-30 times for every symbol. It's much faster to calculate it beforehand and pass pointer to it to the comparison function.


https://reviews.llvm.org/D36941

Files:
  llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp


Index: llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
+++ llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
@@ -169,34 +169,34 @@
   return Error::success();
 }
 
-static bool comparePubSymByAddrAndName(const CVSymbol *LS, const CVSymbol *RS) {
-  assert(LS->kind() == SymbolKind::S_PUB32);
-  assert(RS->kind() == SymbolKind::S_PUB32);
-
-  PublicSym32 PSL =
-      cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(*LS));
-  PublicSym32 PSR =
-      cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(*RS));
-
-  if (PSL.Segment != PSR.Segment)
-    return PSL.Segment < PSR.Segment;
-  if (PSL.Offset != PSR.Offset)
-    return PSL.Offset < PSR.Offset;
-
-  return PSL.Name < PSR.Name;
+static bool comparePubSymByAddrAndName(const std::pair<const CVSymbol *, const  PublicSym32 *> &LS, const std::pair<const CVSymbol *, const PublicSym32 *> &RS)
+{
+  if (LS.second->Segment != RS.second->Segment)
+    return LS.second->Segment < RS.second->Segment;
+  if (LS.second->Offset != RS.second->Offset)
+    return LS.second->Offset < RS.second->Offset;
+
+  return LS.second->Name < RS.second->Name;
 }
 
 /// Compute the address map. The address map is an array of symbol offsets
 /// sorted so that it can be binary searched by address.
 static std::vector<ulittle32_t> computeAddrMap(ArrayRef<CVSymbol> Records) {
   // Make a vector of pointers to the symbols so we can sort it by address.
   // Also gather the symbol offsets while we're at it.
-  std::vector<const CVSymbol *> PublicsByAddr;
+
+  std::vector<PublicSym32> DeserializedPublics;
+  std::vector<std::pair<const CVSymbol *, const PublicSym32 *>> PublicsByAddr;
   std::vector<uint32_t> SymOffsets;
+  DeserializedPublics.reserve (Records.size());
   PublicsByAddr.reserve(Records.size());
+  SymOffsets.reserve(Records.size());
+
   uint32_t SymOffset = 0;
   for (const CVSymbol &Sym : Records) {
-    PublicsByAddr.push_back(&Sym);
+    assert(Sym.kind() == SymbolKind::S_PUB32);
+    DeserializedPublics.push_back (cantFail (SymbolDeserializer::deserializeAs<PublicSym32>(Sym)));
+    PublicsByAddr.emplace_back (&Sym, &DeserializedPublics.back ());
     SymOffsets.push_back(SymOffset);
     SymOffset += Sym.length();
   }
@@ -206,8 +206,8 @@
   // Fill in the symbol offsets in the appropriate order.
   std::vector<ulittle32_t> AddrMap;
   AddrMap.reserve(Records.size());
-  for (const CVSymbol *Sym : PublicsByAddr) {
-    ptrdiff_t Idx = std::distance(Records.data(), Sym);
+  for (auto &Sym : PublicsByAddr) {
+    ptrdiff_t Idx = std::distance(Records.data(), Sym.first);
     assert(Idx >= 0 && size_t(Idx) < Records.size());
     AddrMap.push_back(ulittle32_t(SymOffsets[Idx]));
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D36941.111904.patch
Type: text/x-patch
Size: 2805 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170820/8a124d6b/attachment.bin>


More information about the llvm-commits mailing list