From aee51b4d75089b4e7d9eb20877e2adbf6adea999 Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Fri, 10 Jan 2025 23:42:29 +0800 Subject: [PATCH] [clang-tidy][NFC] optimize cache for config option (#121406) Current implement will cache `OptionsSource` for each path, it will create lots of copy of `OptionsSource` when project has deep nested folder structure. New implement use vector to store `OptionsSource` and only cache the index. It can reduce memory usage and avoid meaningless copy. --- .../clang-tidy/ClangTidyOptions.cpp | 47 ++++++++++--------- .../clang-tidy/ClangTidyOptions.h | 5 +- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp index 445c7f85c900..e1d5df75f3e5 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -337,33 +337,34 @@ FileOptionsBaseProvider::FileOptionsBaseProvider( void FileOptionsBaseProvider::addRawFileOptions( llvm::StringRef AbsolutePath, std::vector &CurOptions) { auto CurSize = CurOptions.size(); - // Look for a suitable configuration file in all parent directories of the // file. Start with the immediate parent directory and move up. - StringRef Path = llvm::sys::path::parent_path(AbsolutePath); - for (StringRef CurrentPath = Path; !CurrentPath.empty(); - CurrentPath = llvm::sys::path::parent_path(CurrentPath)) { - std::optional Result; - - auto Iter = CachedOptions.find(CurrentPath); - if (Iter != CachedOptions.end()) - Result = Iter->second; - - if (!Result) - Result = tryReadConfigFile(CurrentPath); - - if (Result) { - // Store cached value for all intermediate directories. - while (Path != CurrentPath) { + StringRef RootPath = llvm::sys::path::parent_path(AbsolutePath); + auto MemorizedConfigFile = + [this, &RootPath](StringRef CurrentPath) -> std::optional { + const auto Iter = CachedOptions.Memorized.find(CurrentPath); + if (Iter != CachedOptions.Memorized.end()) + return CachedOptions.Storage[Iter->second]; + std::optional OptionsSource = tryReadConfigFile(CurrentPath); + if (OptionsSource) { + const size_t Index = CachedOptions.Storage.size(); + CachedOptions.Storage.emplace_back(OptionsSource.value()); + while (RootPath != CurrentPath) { LLVM_DEBUG(llvm::dbgs() - << "Caching configuration for path " << Path << ".\n"); - if (!CachedOptions.count(Path)) - CachedOptions[Path] = *Result; - Path = llvm::sys::path::parent_path(Path); + << "Caching configuration for path " << RootPath << ".\n"); + CachedOptions.Memorized[RootPath] = Index; + RootPath = llvm::sys::path::parent_path(RootPath); } - CachedOptions[Path] = *Result; - - CurOptions.push_back(*Result); + CachedOptions.Memorized[CurrentPath] = Index; + RootPath = llvm::sys::path::parent_path(CurrentPath); + } + return OptionsSource; + }; + for (StringRef CurrentPath = RootPath; !CurrentPath.empty(); + CurrentPath = llvm::sys::path::parent_path(CurrentPath)) { + if (std::optional Result = + MemorizedConfigFile(CurrentPath)) { + CurOptions.emplace_back(Result.value()); if (!Result->first.InheritParentConfig.value_or(false)) break; } diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h index 85d5a02ebbc1..568f60cf98b2 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -241,7 +241,10 @@ protected: /// \c ConfigHandlers. std::optional tryReadConfigFile(llvm::StringRef Directory); - llvm::StringMap CachedOptions; + struct OptionsCache { + llvm::StringMap Memorized; + llvm::SmallVector Storage; + } CachedOptions; ClangTidyOptions OverrideOptions; ConfigFileHandlers ConfigHandlers; llvm::IntrusiveRefCntPtr FS;