1 //===--- BackgroundIndexRebuild.h - when to rebuild the bg index--*- C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains an implementation detail of the background indexer 10 // (Background.h), which is exposed for testing. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_INDEX_REBUILD_H 15 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_INDEX_REBUILD_H 16 17 #include "index/FileIndex.h" 18 #include "index/Index.h" 19 #include "llvm/Support/Threading.h" 20 #include <cstddef> 21 22 namespace clang { 23 namespace clangd { 24 25 // The BackgroundIndexRebuilder builds the serving data structures periodically 26 // in response to events in the background indexer. The goal is to ensure the 27 // served data stays fairly fresh, without wasting lots of CPU rebuilding it 28 // often. 29 // 30 // The index is always built after a set of shards are loaded from disk. 31 // This happens when clangd discovers a compilation database that we've 32 // previously built an index for. It's a fairly fast process that yields lots 33 // of data, so we wait to get all of it. 34 // 35 // The index is built after indexing a few translation units, if it wasn't built 36 // already. This ensures quick startup if there's no existing index. 37 // Waiting for a few random TUs yields coverage of the most common headers. 38 // 39 // The index is rebuilt every N TUs, to keep if fresh as files are indexed. 40 // 41 // The index is rebuilt every time the queue goes idle, if it's stale. 42 // 43 // All methods are threadsafe. They're called after FileSymbols is updated 44 // etc. Without external locking, the rebuilt index may include more updates 45 // than intended, which is fine. 46 // 47 // This class is exposed in the header so it can be tested. 48 class BackgroundIndexRebuilder { 49 public: BackgroundIndexRebuilder(SwapIndex * Target,FileSymbols * Source,unsigned Threads)50 BackgroundIndexRebuilder(SwapIndex *Target, FileSymbols *Source, 51 unsigned Threads) 52 : TUsBeforeFirstBuild(Threads), Target(Target), Source(Source) {} 53 54 // Called to indicate a TU has been indexed. 55 // May rebuild, if enough TUs have been indexed. 56 void indexedTU(); 57 // Called to indicate that all worker threads are idle. 58 // May reindex, if the index is not up to date. 59 void idle(); 60 // Called to indicate we're going to load a batch of shards from disk. 61 // startLoading() and doneLoading() must be paired, but multiple loading 62 // sessions may happen concurrently. 63 void startLoading(); 64 // Called to indicate some shards were actually loaded from disk. 65 void loadedShard(size_t ShardCount); 66 // Called to indicate we're finished loading shards from disk. 67 // May rebuild (if any were loaded). 68 void doneLoading(); 69 70 // Ensures we won't start any more rebuilds. 71 void shutdown(); 72 73 // Thresholds for rebuilding as TUs get indexed. Exposed for testing. 74 const unsigned TUsBeforeFirstBuild; // Typically one per worker thread. 75 const unsigned TUsBeforeRebuild = 100; 76 77 private: 78 // Run Check under the lock, and rebuild if it returns true. 79 void maybeRebuild(const char *Reason, std::function<bool()> Check); 80 bool enoughTUsToRebuild() const; 81 82 // All transient state is guarded by the mutex. 83 std::mutex Mu; 84 bool ShouldStop = false; 85 // Index builds are versioned. ActiveVersion chases StartedVersion. 86 unsigned StartedVersion = 0; 87 unsigned ActiveVersion = 0; 88 // How many TUs have we indexed so far since startup? 89 unsigned IndexedTUs = 0; 90 unsigned IndexedTUsAtLastRebuild = 0; 91 // Are we loading shards? May be multiple concurrent sessions. 92 unsigned Loading = 0; 93 unsigned LoadedShards; // In the current loading session. 94 95 SwapIndex *Target; 96 FileSymbols *Source; 97 }; 98 99 } // namespace clangd 100 } // namespace clang 101 102 #endif 103