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