Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang][modules] Remove preloaded SLocEntries from PCM files #66962

Merged
merged 6 commits into from
Oct 6, 2023

Conversation

jansvoboda11
Copy link
Contributor

This commit removes the list of SLocEntry offsets to preload eagerly from PCM files. Commit introducing this functionality (258ae54) doesn't clarify why this would be more performant than the lazy approach used regularly.

Currently, the only SLocEntry the reader is supposed to preload is the predefines buffer, but in my experience, it's not actually referenced in most modules, so the time spent deserializing its SLocEntry is wasted. This is especially noticeable in the dependency scanner, where this change brings 4.56% speedup on my benchmark.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:modules C++20 modules and Clang Header Modules labels Sep 20, 2023
@llvmbot
Copy link
Member

llvmbot commented Sep 20, 2023

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-modules

Changes

This commit removes the list of SLocEntry offsets to preload eagerly from PCM files. Commit introducing this functionality (258ae54) doesn't clarify why this would be more performant than the lazy approach used regularly.

Currently, the only SLocEntry the reader is supposed to preload is the predefines buffer, but in my experience, it's not actually referenced in most modules, so the time spent deserializing its SLocEntry is wasted. This is especially noticeable in the dependency scanner, where this change brings 4.56% speedup on my benchmark.


Full diff: https://github.com/llvm/llvm-project/pull/66962.diff

4 Files Affected:

  • (modified) clang/include/clang/Serialization/ASTBitCodes.h (+2-8)
  • (modified) clang/include/clang/Serialization/ModuleFile.h (-3)
  • (modified) clang/lib/Serialization/ASTReader.cpp (-23)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (-8)
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 9e115f2a5cce3f9..6cbaff71cc33960 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -51,7 +51,7 @@ const unsigned VERSION_MAJOR = 29;
 /// for the previous version could still support reading the new
 /// version by ignoring new kinds of subblocks), this number
 /// should be increased.
-const unsigned VERSION_MINOR = 0;
+const unsigned VERSION_MINOR = 1;
 
 /// An ID number that refers to an identifier in an AST file.
 ///
@@ -524,13 +524,7 @@ enum ASTRecordTypes {
   /// of source-location information.
   SOURCE_LOCATION_OFFSETS = 14,
 
-  /// Record code for the set of source location entries
-  /// that need to be preloaded by the AST reader.
-  ///
-  /// This set contains the source location entry for the
-  /// predefines buffer and for any file entries that need to be
-  /// preloaded.
-  SOURCE_LOCATION_PRELOADS = 15,
+  /// ID 15 used to be for source location entry preloads.
 
   /// Record code for the set of ext_vector type names.
   EXT_VECTOR_DECLS = 16,
diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h
index 0af5cae6aebc375..48be8676cc26a4c 100644
--- a/clang/include/clang/Serialization/ModuleFile.h
+++ b/clang/include/clang/Serialization/ModuleFile.h
@@ -292,9 +292,6 @@ class ModuleFile {
   /// AST file.
   const uint32_t *SLocEntryOffsets = nullptr;
 
-  /// SLocEntries that we're going to preload.
-  SmallVector<uint64_t, 4> PreloadSLocEntries;
-
   /// Remapping table for source locations in this module.
   ContinuousRangeMap<SourceLocation::UIntTy, SourceLocation::IntTy, 2>
       SLocRemap;
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 0952244d037a77c..e796617455ac390 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -3226,7 +3226,6 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
       case SOURCE_LOCATION_OFFSETS:
       case MODULE_OFFSET_MAP:
       case SOURCE_MANAGER_LINE_TABLE:
-      case SOURCE_LOCATION_PRELOADS:
       case PPD_ENTITIES_OFFSETS:
       case HEADER_SEARCH_TABLE:
       case IMPORTED_MODULES:
@@ -3576,18 +3575,6 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
       ParseLineTable(F, Record);
       break;
 
-    case SOURCE_LOCATION_PRELOADS: {
-      // Need to transform from the local view (1-based IDs) to the global view,
-      // which is based off F.SLocEntryBaseID.
-      if (!F.PreloadSLocEntries.empty())
-        return llvm::createStringError(
-            std::errc::illegal_byte_sequence,
-            "Multiple SOURCE_LOCATION_PRELOADS records in AST file");
-
-      F.PreloadSLocEntries.swap(Record);
-      break;
-    }
-
     case EXT_VECTOR_DECLS:
       for (unsigned I = 0, N = Record.size(); I != N; ++I)
         ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I]));
@@ -4417,16 +4404,6 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ModuleKind Type,
   for (ImportedModule &M : Loaded) {
     ModuleFile &F = *M.Mod;
 
-    // Preload SLocEntries.
-    for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {
-      int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
-      // Load it through the SourceManager and don't call ReadSLocEntry()
-      // directly because the entry may have already been loaded in which case
-      // calling ReadSLocEntry() directly would trigger an assertion in
-      // SourceManager.
-      SourceMgr.getLoadedSLocEntryByID(Index);
-    }
-
     // Map the original source file ID into the ID space of the current
     // compilation.
     if (F.OriginalSourceFileID.isValid())
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 65bee806d2c5571..3392243d7ac4ba7 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -838,7 +838,6 @@ void ASTWriter::WriteBlockInfoBlock() {
   RECORD(METHOD_POOL);
   RECORD(PP_COUNTER_VALUE);
   RECORD(SOURCE_LOCATION_OFFSETS);
-  RECORD(SOURCE_LOCATION_PRELOADS);
   RECORD(EXT_VECTOR_DECLS);
   RECORD(UNUSED_FILESCOPED_DECLS);
   RECORD(PPD_ENTITIES_OFFSETS);
@@ -2137,7 +2136,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
   // entry, which is always the same dummy entry.
   std::vector<uint32_t> SLocEntryOffsets;
   uint64_t SLocEntryOffsetsBase = Stream.GetCurrentBitNo();
-  RecordData PreloadSLocs;
   SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1);
   for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size();
        I != N; ++I) {
@@ -2213,9 +2211,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
         Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
                                   StringRef(Name.data(), Name.size() + 1));
         EmitBlob = true;
-
-        if (Name == "<built-in>")
-          PreloadSLocs.push_back(SLocEntryOffsets.size());
       }
 
       if (EmitBlob) {
@@ -2277,9 +2272,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
     Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,
                               bytes(SLocEntryOffsets));
   }
-  // Write the source location entry preloads array, telling the AST
-  // reader which source locations entries it should load eagerly.
-  Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs);
 
   // Write the line table. It depends on remapping working, so it must come
   // after the source location offsets.

Copy link
Collaborator

@benlangmuir benlangmuir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in my experience, it's not actually referenced in most modules

Can you clarify what you looked at here? I assume you checked non-scanner modules as well?

clang/include/clang/Serialization/ASTBitCodes.h Outdated Show resolved Hide resolved
@jansvoboda11
Copy link
Contributor Author

in my experience, it's not actually referenced in most modules

Can you clarify what you looked at here? I assume you checked non-scanner modules as well?

I took a typical Xcode project and chose one TU that happens to transitively depend on 37 modules. I built it with implicit modules and scanned its dependencies while counting all SourceManager requests specifically asking for the predefines SLocEntry:

workload cache before after change [%]
implicit build clean 2077 1197 -42.4
implicit build full 84 19 -77.3
scan clean 1015 568 -44.0
scan full 39 18 -53.8

So saying most was incorrect. The data suggests that importers don't care about the predefines of ~43% of their transitive dependencies. Note that this number is higher when the cache is full, where the percentage only represents requests issued from the main TU. So it makes sense that deserializing predefines SLocEntry on-demand is a performance win, especially since it shouldn't have any overhead compared to the preloading approach.

Copy link
Collaborator

@benlangmuir benlangmuir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM other than my nit about the comment

@jansvoboda11
Copy link
Contributor Author

The "Index/annotate-module.m" test fails with this patch. For run line 29, the previous input is:

Punctuation: "#" [1:1 - 1:2] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Identifier: "include" [1:2 - 1:9] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Punctuation: "<" [1:10 - 1:11] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Identifier: "Module" [1:11 - 1:17] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Punctuation: "/" [1:17 - 1:18] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Identifier: "Sub2" [1:18 - 1:22] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Punctuation: "." [1:22 - 1:23] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Identifier: "h" [1:23 - 1:24] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Punctuation: ">" [1:24 - 1:25] inclusion directive=Module/Sub2.h (/Users/Jan/Code/upstream-llvm/clang/test/Index/../Modules/Inputs/Module.framework/Headers/Sub2.h)
Keyword: "int" [2:1 - 2:4] VarDecl=Module_Sub:2:6
Punctuation: "*" [2:5 - 2:6] VarDecl=Module_Sub:2:6
Identifier: "Module_Sub" [2:6 - 2:16] VarDecl=Module_Sub:2:6
Punctuation: ";" [2:16 - 2:17]
...

while the current output is:

Punctuation: "#" [1:1 - 1:2] preprocessing directive=
Identifier: "include" [1:2 - 1:9] preprocessing directive=
Punctuation: "<" [1:10 - 1:11] preprocessing directive=
Identifier: "Module" [1:11 - 1:17] preprocessing directive=
Punctuation: "/" [1:17 - 1:18] preprocessing directive=
Identifier: "Sub2" [1:18 - 1:22] preprocessing directive=
Punctuation: "." [1:22 - 1:23] preprocessing directive=
Identifier: "h" [1:23 - 1:24] preprocessing directive=
Punctuation: ">" [1:24 - 1:25] preprocessing directive=
Keyword: "int" [2:1 - 2:4] VarDecl=Module_Sub:2:6
Punctuation: "*" [2:5 - 2:6] VarDecl=Module_Sub:2:6
Identifier: "Module_Sub" [2:6 - 2:16] VarDecl=Module_Sub:2:6
Punctuation: ";" [2:16 - 2:17]
...

This seems to be the stack trace where things go wrong:

clang_annotateTokens()
  PreprocessingRecord::getPreprocessedEntitiesInRange(Slow)
    ASTReader::findPreprocessedEntitiesInRange()
      ASTReader::findPreprocessedEntity()
        SourceManager::isBeforeInTranslationUnit()
          SourceManager::isInTheSameTranslationUnit()
            MoveUpIncludeHierarchy()
              SourceManager::getDecomposedIncludedLoc()

Here's my current understanding:

  • previously:
    • ModuleFile gets created with untranslated IncludeLoc
    • built-in buffer is preloaded and inherits the untranslated IncludeLoc
    • ModuleFile::IncludeLoc gets translated
    • SourceManager::getDecomposedIncludedLoc() reports the incorrect IncludeLoc for the built-in buffer
  • currently:
    • ModuleFile gets created with untranslated IncludeLoc
    • ModuleFile::IncludeLoc gets translated
    • built-in buffer is loaded on-demand and inherits the translated IncludeLoc
    • SourceManager::getDecomposedIncludedLoc() reports the correct IncludeLoc

I need to dig a bit deeper to figure out what exactly needs fixing here.

@jansvoboda11
Copy link
Contributor Author

Ok, the comment below seems to suggests that the built-ins buffers are not considered to be part of any TU:

bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
                                              SourceLocation RHS) const {
  // ...

  if (isInTheSameTranslationUnit(LHS, RHS))
    return X;

  // If we arrived here, the location is either in a built-ins buffer or
  // associated with global inline asm. PR5662 and PR22576 are examples.

  // ...
}

I changed SourceManager::isInTheSameTranslationUnit() to check for that case explicitly instead of relying on the fact/bug that built-ins buffers happened to be assigned an untranslated include SourceLocation.

@llvmbot llvmbot added the clang:frontend Language frontend issues, e.g. anything involving "Sema" label Sep 25, 2023
@benlangmuir
Copy link
Collaborator

I changed SourceManager::isInTheSameTranslationUnit() to check for that case explicitly instead of relying on the fact/bug that built-ins buffers happened to be assigned an untranslated include SourceLocation.

What is the translated location you get here? It's hard for me to tell if the comment in isBeforeInTranslationUnit is describing the desired behaviour or just a consequence of how it happened to work at the time.

@jansvoboda11
Copy link
Contributor Author

jansvoboda11 commented Sep 28, 2023

I changed SourceManager::isInTheSameTranslationUnit() to check for that case explicitly instead of relying on the fact/bug that built-ins buffers happened to be assigned an untranslated include SourceLocation.

What is the translated location you get here? It's hard for me to tell if the comment in isBeforeInTranslationUnit is describing the desired behaviour or just a consequence of how it happened to work at the time.

When a module is built, its SourceLocation offsets go from 0 to N. When it's imported, they are remapped into the range from 232-N to 232.

So the fact that we didn't remap the offset of the built-ins buffer meant it was not considered part of the imported module. This made isInTheSameTranslationUnit(<built-ins>, header) return [false, false] and the special case in isBeforeInTranslationUnit() would make sure to return true in order to enforce that the <built-ins> buffer always compares < to other offsets in the module.

It took me a while to figure out why that is desired. My understanding is that whether one offset is before another can't be just simple comparison of the numeric values. (More details on this are in isInTheSameTranslationUnit().)

Here's a little example of how this ends up working with modules:

entry ID [t] offset isBefore(?, t(250)) isBefore(t(250), ?)
dummy 0 [-6] <0,1) yes no
modulemap 1 [-5] <1,10) yes no
<module-includes> 2 [-4] <10,100) yes no
<built-in> 3 [-3] <100,200) no yes
header 4 [-2] <200,300) yes -> no no -> yes

The <module-includes> buffer is parent of the header, but the <built-in> buffer ends up being created in between them. This causes the isBefore relationships to not be sorted/partitioned, as one might expect.

This is the reason the binary search in ASTReader::findPreprocessedEntitiesInRange() broke.

So the special case in isBeforeInTranslationUnit() that moves <built-in> before all other entries makes sense, but now needs to happen earlier, before calling isInTheSameTranslationUnit(). That's what I've done in the latest commit, and it actually fixes "Index/annotate-module.m". (I guess we should also consider merging both of those functions, because isInTheSameTranslationUnit() doesn't really stand on its own now.) Unfortunately, "SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp" started failing, so I'll look into that next.

@benlangmuir, let me know if this explanation makes sense.

Also adding @sam-mccall as a reviewer, since he's worked in this area recently.

@benlangmuir
Copy link
Collaborator

Thanks for laying it out. I also find this easier to understand in your latest changes because the comments in isBeforeInTranslationUnit lay out the intended ordering without relying on isInTheSameTranslationUnit returning false for builtin buffers, which is the part that seemed suspect.

@sam-mccall
Copy link
Collaborator

Ripping out this feature sounds great, as does fixing the non-translation of builtin buffer locations.

My only concern is that this will make isBeforeInTranslationUnit more expensive. A loc being in one of these special "" is the rare case, and the code recognizing them doesn't look fast (which didn't previously matter, as we only reached it rarely).

That said, isBeforeInTranslationUnit is slow already, and I don't think it's hot in clang, moreso in tools like clang-tidy whose performance is less-critical. So let's make it right, and then optimize it again if problems arise.

This commit removes the list of SLocEntry offsets to preload eagerly from PCM files. Commit introducing this functionality (258ae54) doesn't clarify why this would be more performant than the lazy approach used regularly.

Currently, the only SLocEntry the reader is supposed to preload is the predefines buffer, but in my experience, it's not actually referenced in most modules, so the time spent deserializing its SLocEntry is wasted. This is especially noticeable in the dependency scanner, where this change brings 4.56% speedup on my benchmark.
@jansvoboda11
Copy link
Contributor Author

I got around investigating "SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp" and found out it uses this pattern:

%clang_cc1 ... -include %s %s

This means FileID(1) is the main input file %s and FileID(2) is the built-ins buffer that includes %s as FileID(3).

Since I moved up the special-casing of built-ins buffer up in my last commit, it was happening before we got chance to walk up from FileID(3) to FileID(2), meaning it wasn't kicking in. I think we need to sink the special-casing into isInTheSameTranslationUnit() and apply it to whatever FileID we end up with after not finding the common ancestor.

@jansvoboda11
Copy link
Contributor Author

jansvoboda11 commented Oct 2, 2023

Also, it seems that the code previously assumed that two SourceLocations are in the same TU iff they have the same common ancestor. There are at least two counter-examples to this:

  • The built-ins buffer doesn't have any ancestor, but still is part of the TU.
  • With implicit modules (or lazy loaded explicit modules), all top-level SLocEntries loaded from PCM files have their include location adjusted to the import statement, so they became part of the importer SLocEntry tree and are all considered to be part of the importing TU.

I started tracking the SLocEntries allocated for each AST file and use that to cut off the include chain walk in order to stay in the same TU we started in. This basically make sure we don't skip the special case for loaded built-ins buffers.

@jansvoboda11
Copy link
Contributor Author

Turns out some clients are calling isBeforeInTranslationUnit() before checking if both SourceLocations are indeed in the same TU. I left behind a FIXME to call llvm_unreachable(), but for now, I just compare the FileIDs to keep things working.

@jansvoboda11
Copy link
Contributor Author

I don't understand why the tie-breaking code calls the previously visited FileID a parent. We're walking up the include/expansion tree, so I think it should be called child instead. LMK if I'm misunderstanding.

@tahonermann
Copy link
Contributor

That said, isBeforeInTranslationUnit is slow already, and I don't think it's hot in clang, moreso in tools like clang-tidy whose performance is less-critical. So let's make it right, and then optimize it again if problems arise.

It may not be a hot function in Clang itself, but it is quite hot for some downstream Clang forks. While at Coverity, I had to avoid direct use of it because it was far too slow. Anything that speeds it up would be appreciated.

@jansvoboda11
Copy link
Contributor Author

That said, isBeforeInTranslationUnit is slow already, and I don't think it's hot in clang, moreso in tools like clang-tidy whose performance is less-critical. So let's make it right, and then optimize it again if problems arise.

It may not be a hot function in Clang itself, but it is quite hot for some downstream Clang forks. While at Coverity, I had to avoid direct use of it because it was far too slow. Anything that speeds it up would be appreciated.

That's good to know, thanks! I think in it's current version, this patch shouldn't make that function slower, but I'll verify this after I get a green light on the semantic changes.

clang/lib/Basic/SourceManager.cpp Outdated Show resolved Hide resolved
clang/include/clang/Basic/SourceManager.h Outdated Show resolved Hide resolved
clang/lib/Basic/SourceManager.cpp Show resolved Hide resolved
clang/lib/Basic/SourceManager.cpp Outdated Show resolved Hide resolved
clang/lib/Basic/SourceManager.cpp Outdated Show resolved Hide resolved
clang/lib/Basic/SourceManager.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@benlangmuir benlangmuir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for iterating! I find the current implementation much clearer.

The only thing I might quibble about is the "child" vs. "parent" terminology you changed: I think it's fairly ambiguous either way, because the node is the "child" from the perspective of a top-down include hierarchy, but it's the "parent" from the perspective of the bottom-up search. You could maybe change it to IncludedFile or something, but I don't feel very strongly about it. Child is no worse than parent so if you prefer child I don't think you need to change it.

@jansvoboda11
Copy link
Contributor Author

Thanks for iterating! I find the current implementation much clearer.

Thanks for your patience!

The only thing I might quibble about is the "child" vs. "parent" terminology you changed: I think it's fairly ambiguous either way, because the node is the "child" from the perspective of a top-down include hierarchy, but it's the "parent" from the perspective of the bottom-up search. You could maybe change it to IncludedFile or something, but I don't feel very strongly about it. Child is no worse than parent so if you prefer child I don't think you need to change it.

I understand. My problem with using "parent" here is that we're using "parent" just a couple lines above to describe the opposite relationship:

// - one loc is a parent of the other (we consider the parent as "first")

So I believe framing all the relationships in terms of the top-down include/expansion hierarchy makes more sense than mixing them up with the bottom-up tree walk.

@jansvoboda11
Copy link
Contributor Author

@sam-mccall Do you have any additional feedback? You might want to check how this PR and #66966 impact performance for you.

@jansvoboda11 jansvoboda11 merged commit 0dfb5da into llvm:main Oct 6, 2023
@jansvoboda11 jansvoboda11 deleted the no-eager-sloc-entry branch October 6, 2023 19:50
jansvoboda11 added a commit to swiftlang/llvm-project that referenced this pull request Oct 8, 2023
)

This commit removes the list of SLocEntry offsets to preload eagerly
from PCM files. Commit introducing this functionality (258ae54) doesn't
clarify why this would be more performant than the lazy approach used
regularly.

Currently, the only SLocEntry the reader is supposed to preload is the
predefines buffer, but in my experience, it's not actually referenced in
most modules, so the time spent deserializing its SLocEntry is wasted.
This is especially noticeable in the dependency scanner, where this
change brings 4.56% speedup on my benchmark.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants