Index: clangd/Threading.h =================================================================== --- clangd/Threading.h +++ clangd/Threading.h @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace clang { @@ -115,6 +116,13 @@ mutable std::condition_variable TasksReachedZero; std::size_t InFlightTasks = 0; }; + +enum class ThreadPriority { + Low = 0, + Normal = 1, +}; +void setThreadPriority(std::thread &T, ThreadPriority Priority); + } // namespace clangd } // namespace clang #endif Index: clangd/Threading.cpp =================================================================== --- clangd/Threading.cpp +++ clangd/Threading.cpp @@ -1,9 +1,13 @@ #include "Threading.h" #include "Trace.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/Config/config.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Threading.h" #include +#ifdef HAVE_PTHREAD_H +#include +#endif using namespace llvm; namespace clang { @@ -97,5 +101,15 @@ CV.wait_until(Lock, D.time()); } +void setThreadPriority(std::thread &T, ThreadPriority Priority) { +#ifdef HAVE_PTHREAD_H + sched_param priority; + priority.sched_priority = 0; + pthread_setschedparam( + T.native_handle(), + Priority == ThreadPriority::Low ? SCHED_IDLE : SCHED_OTHER, &priority); +#endif +} + } // namespace clangd } // namespace clang Index: clangd/index/Background.h =================================================================== --- clangd/index/Background.h +++ clangd/index/Background.h @@ -16,6 +16,7 @@ #include "index/Index.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/SHA1.h" +#include "llvm/Support/Threading.h" #include #include #include @@ -34,7 +35,8 @@ // FIXME: resource-dir injection should be hoisted somewhere common. BackgroundIndex(Context BackgroundContext, StringRef ResourceDir, const FileSystemProvider &, - ArrayRef URISchemes = {}); + ArrayRef URISchemes = {}, + size_t ThreadPoolSize = llvm::hardware_concurrency()); ~BackgroundIndex(); // Blocks while the current task finishes. // Enqueue a translation unit for indexing. @@ -66,7 +68,7 @@ llvm::StringMap FileHash; // Digest of indexed file. // queue management - using Task = std::function; // FIXME: use multiple worker threads. + using Task = std::function; void run(); // Main loop executed by Thread. Runs tasks from Queue. void enqueueLocked(tooling::CompileCommand Cmd); std::mutex QueueMu; @@ -74,7 +76,7 @@ std::condition_variable QueueCV; bool ShouldStop = false; std::deque Queue; - std::thread Thread; // Must be last, spawned thread reads instance vars. + std::vector ThreadPool; // FIXME: Abstract this away. }; } // namespace clangd Index: clangd/index/Background.cpp =================================================================== --- clangd/index/Background.cpp +++ clangd/index/Background.cpp @@ -11,6 +11,7 @@ #include "ClangdUnit.h" #include "Compiler.h" #include "Logger.h" +#include "Threading.h" #include "Trace.h" #include "index/IndexAction.h" #include "index/MemIndex.h" @@ -25,14 +26,26 @@ BackgroundIndex::BackgroundIndex(Context BackgroundContext, StringRef ResourceDir, const FileSystemProvider &FSProvider, - ArrayRef URISchemes) + ArrayRef URISchemes, + size_t ThreadPoolSize) : SwapIndex(make_unique()), ResourceDir(ResourceDir), FSProvider(FSProvider), BackgroundContext(std::move(BackgroundContext)), - URISchemes(URISchemes), Thread([this] { run(); }) {} + URISchemes(URISchemes) { + assert(ThreadPoolSize > 0 && "Thread pool size can't be zero."); + while (ThreadPoolSize--) { + ThreadPool.emplace_back([this] { run(); }); + // Set priority to low, since background indexing is a long running task we + // do not want to eat up cpu when there are any other high priority threads. + // FIXME: In the future we might want a more general way of handling this to + // support a tasks with various priorities. + setThreadPriority(ThreadPool.back(), ThreadPriority::Low); + } +} BackgroundIndex::~BackgroundIndex() { stop(); - Thread.join(); + for (auto &Thread : ThreadPool) + Thread.join(); } void BackgroundIndex::stop() { @@ -44,7 +57,7 @@ } void BackgroundIndex::run() { - WithContext Background(std::move(BackgroundContext)); + WithContext Background(BackgroundContext.clone()); while (true) { Optional Task; {