Skip to content

Commit 773ad55

Browse files
committed
[index] Fix performance regression with indexing macros
When using FileIndexRecord with macros, symbol references can be seen out of source order, which was causing a regression to insert the symbols into a vector. Instead, we now lazily sort the vector. The impact is small on most code, but in very large files with many macro references (M) near the beginning of the file followed by many decl references (D) it was O(M*D). A particularly bad protobuf-generated header was observed with a 100% regression in practice. rdar://78628133
1 parent 1de18ad commit 773ad55

File tree

2 files changed

+16
-22
lines changed

2 files changed

+16
-22
lines changed

clang/lib/Index/FileIndexRecord.cpp

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,32 @@
1717
using namespace clang;
1818
using namespace clang::index;
1919

20-
static void addOccurrence(std::vector<DeclOccurrence> &Decls,
21-
DeclOccurrence Info) {
22-
auto IsNextOccurence = [&]() -> bool {
23-
if (Decls.empty())
24-
return true;
25-
auto &Last = Decls.back();
26-
return Last.Offset < Info.Offset;
27-
};
28-
29-
if (IsNextOccurence()) {
30-
Decls.push_back(std::move(Info));
31-
return;
20+
ArrayRef<DeclOccurrence>
21+
FileIndexRecord::getDeclOccurrencesSortedByOffset() const {
22+
if (!IsSorted) {
23+
llvm::stable_sort(Decls,
24+
[](const DeclOccurrence &A, const DeclOccurrence &B) {
25+
return A.Offset < B.Offset;
26+
});
27+
IsSorted = true;
3228
}
33-
34-
// We keep Decls in order as we need to access them in this order in all cases.
35-
auto It = llvm::upper_bound(Decls, Info);
36-
Decls.insert(It, std::move(Info));
29+
return Decls;
3730
}
3831

3932
void FileIndexRecord::addDeclOccurence(SymbolRoleSet Roles, unsigned Offset,
4033
const Decl *D,
4134
ArrayRef<SymbolRelation> Relations) {
4235
assert(D->isCanonicalDecl() &&
4336
"Occurrences should be associated with their canonical decl");
44-
addOccurrence(Decls, DeclOccurrence(Roles, Offset, D, Relations));
37+
IsSorted = false;
38+
Decls.emplace_back(Roles, Offset, D, Relations);
4539
}
4640

4741
void FileIndexRecord::addMacroOccurence(SymbolRoleSet Roles, unsigned Offset,
4842
const IdentifierInfo *Name,
4943
const MacroInfo *MI) {
50-
addOccurrence(Decls, DeclOccurrence(Roles, Offset, Name, MI));
44+
IsSorted = false;
45+
Decls.emplace_back(Roles, Offset, Name, MI);
5146
}
5247

5348
void FileIndexRecord::removeHeaderGuardMacros() {

clang/lib/Index/FileIndexRecord.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,13 @@ class FileIndexRecord {
2727
private:
2828
FileID FID;
2929
bool IsSystem;
30-
std::vector<DeclOccurrence> Decls;
30+
mutable bool IsSorted = false;
31+
mutable std::vector<DeclOccurrence> Decls;
3132

3233
public:
3334
FileIndexRecord(FileID FID, bool IsSystem) : FID(FID), IsSystem(IsSystem) {}
3435

35-
ArrayRef<DeclOccurrence> getDeclOccurrencesSortedByOffset() const {
36-
return Decls;
37-
}
36+
ArrayRef<DeclOccurrence> getDeclOccurrencesSortedByOffset() const;
3837

3938
FileID getFileID() const { return FID; }
4039
bool isSystem() const { return IsSystem; }

0 commit comments

Comments
 (0)