summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra
diff options
context:
space:
mode:
authorKadir Cetinkaya <kadircet@google.com>2018-12-17 12:30:27 +0000
committerKadir Cetinkaya <kadircet@google.com>2018-12-17 12:30:27 +0000
commit375c54fd1e8833570013d6f44e7bd09dc87d7211 (patch)
tree2e047c36be01801f69235dfef1af1c3810b7cf2f /clang-tools-extra
parent9af1d2d10f1fc4c6bc46656441926a3d0a7fc7ae (diff)
downloadbcm5719-llvm-375c54fd1e8833570013d6f44e7bd09dc87d7211.tar.gz
bcm5719-llvm-375c54fd1e8833570013d6f44e7bd09dc87d7211.zip
[clangd] Only reduce priority of a thread for indexing.
Summary: We'll soon have tasks pending for reading shards from disk, we want them to have normal priority. Because: - They are not CPU intensive, mostly IO bound. - Give a good coverage for the project at startup, therefore it is worth spending some cycles. - We have only one task per whole CDB rather than one task per file. Reviewers: ilya-biryukov Subscribers: ioeric, MaskRay, jkorous, arphaman, jfb, cfe-commits Differential Revision: https://reviews.llvm.org/D55315 llvm-svn: 349345
Diffstat (limited to 'clang-tools-extra')
-rw-r--r--clang-tools-extra/clangd/Threading.cpp4
-rw-r--r--clang-tools-extra/clangd/Threading.h2
-rw-r--r--clang-tools-extra/clangd/index/Background.cpp86
-rw-r--r--clang-tools-extra/clangd/index/Background.h5
4 files changed, 58 insertions, 39 deletions
diff --git a/clang-tools-extra/clangd/Threading.cpp b/clang-tools-extra/clangd/Threading.cpp
index cfb5e02a3f3..abfe0f497ca 100644
--- a/clang-tools-extra/clangd/Threading.cpp
+++ b/clang-tools-extra/clangd/Threading.cpp
@@ -112,13 +112,13 @@ void wait(std::unique_lock<std::mutex> &Lock, std::condition_variable &CV,
static std::atomic<bool> AvoidThreadStarvation = {false};
-void setThreadPriority(std::thread &T, ThreadPriority Priority) {
+void setCurrentThreadPriority(ThreadPriority Priority) {
// Some *really* old glibcs are missing SCHED_IDLE.
#if defined(__linux__) && defined(SCHED_IDLE)
sched_param priority;
priority.sched_priority = 0;
pthread_setschedparam(
- T.native_handle(),
+ pthread_self(),
Priority == ThreadPriority::Low && !AvoidThreadStarvation ? SCHED_IDLE
: SCHED_OTHER,
&priority);
diff --git a/clang-tools-extra/clangd/Threading.h b/clang-tools-extra/clangd/Threading.h
index 628dd558661..4c553288a24 100644
--- a/clang-tools-extra/clangd/Threading.h
+++ b/clang-tools-extra/clangd/Threading.h
@@ -122,7 +122,7 @@ enum class ThreadPriority {
Low = 0,
Normal = 1,
};
-void setThreadPriority(std::thread &T, ThreadPriority Priority);
+void setCurrentThreadPriority(ThreadPriority Priority);
// Avoid the use of scheduler policies that may starve low-priority threads.
// This prevents tests from timing out on loaded systems.
// Affects subsequent setThreadPriority() calls.
diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp
index 897c513830f..c168038f775 100644
--- a/clang-tools-extra/clangd/index/Background.cpp
+++ b/clang-tools-extra/clangd/index/Background.cpp
@@ -22,6 +22,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SHA1.h"
@@ -135,14 +136,8 @@ BackgroundIndex::BackgroundIndex(
})) {
assert(ThreadPoolSize > 0 && "Thread pool size can't be zero.");
assert(this->IndexStorageFactory && "Storage factory can not be null!");
- while (ThreadPoolSize--) {
+ 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 tasks with various priorities.
- setThreadPriority(ThreadPool.back(), ThreadPriority::Low);
- }
}
BackgroundIndex::~BackgroundIndex() {
@@ -163,6 +158,7 @@ void BackgroundIndex::run() {
WithContext Background(BackgroundContext.clone());
while (true) {
Optional<Task> Task;
+ ThreadPriority Priority;
{
std::unique_lock<std::mutex> Lock(QueueMu);
QueueCV.wait(Lock, [&] { return ShouldStop || !Queue.empty(); });
@@ -172,10 +168,16 @@ void BackgroundIndex::run() {
return;
}
++NumActiveTasks;
- Task = std::move(Queue.front());
+ std::tie(Task, Priority) = std::move(Queue.front());
Queue.pop_front();
}
+
+ if (Priority != ThreadPriority::Normal)
+ setCurrentThreadPriority(Priority);
(*Task)();
+ if (Priority != ThreadPriority::Normal)
+ setCurrentThreadPriority(ThreadPriority::Normal);
+
{
std::unique_lock<std::mutex> Lock(QueueMu);
assert(NumActiveTasks > 0 && "before decrementing");
@@ -193,44 +195,60 @@ bool BackgroundIndex::blockUntilIdleForTest(
}
void BackgroundIndex::enqueue(const std::vector<std::string> &ChangedFiles) {
- enqueueTask([this, ChangedFiles] {
- trace::Span Tracer("BackgroundIndexEnqueue");
- // We're doing this asynchronously, because we'll read shards here too.
- // FIXME: read shards here too.
-
- log("Enqueueing {0} commands for indexing", ChangedFiles.size());
- SPAN_ATTACH(Tracer, "files", int64_t(ChangedFiles.size()));
-
- // We shuffle the files because processing them in a random order should
- // quickly give us good coverage of headers in the project.
- std::vector<unsigned> Permutation(ChangedFiles.size());
- std::iota(Permutation.begin(), Permutation.end(), 0);
- std::mt19937 Generator(std::random_device{}());
- std::shuffle(Permutation.begin(), Permutation.end(), Generator);
-
- for (const unsigned I : Permutation)
- enqueue(ChangedFiles[I]);
- });
+ enqueueTask(
+ [this, ChangedFiles] {
+ trace::Span Tracer("BackgroundIndexEnqueue");
+ // We're doing this asynchronously, because we'll read shards here too.
+ // FIXME: read shards here too.
+
+ log("Enqueueing {0} commands for indexing", ChangedFiles.size());
+ SPAN_ATTACH(Tracer, "files", int64_t(ChangedFiles.size()));
+
+ // We shuffle the files because processing them in a random order should
+ // quickly give us good coverage of headers in the project.
+ std::vector<unsigned> Permutation(ChangedFiles.size());
+ std::iota(Permutation.begin(), Permutation.end(), 0);
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Permutation.begin(), Permutation.end(), Generator);
+
+ for (const unsigned I : Permutation)
+ enqueue(ChangedFiles[I]);
+ },
+ ThreadPriority::Normal);
}
void BackgroundIndex::enqueue(const std::string &File) {
ProjectInfo Project;
if (auto Cmd = CDB.getCompileCommand(File, &Project)) {
auto *Storage = IndexStorageFactory(Project.SourceRoot);
+ // 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.
enqueueTask(Bind(
- [this, File, Storage](tooling::CompileCommand Cmd) {
- Cmd.CommandLine.push_back("-resource-dir=" + ResourceDir);
- if (auto Error = index(std::move(Cmd), Storage))
- log("Indexing {0} failed: {1}", File, std::move(Error));
- },
- std::move(*Cmd)));
+ [this, File, Storage](tooling::CompileCommand Cmd) {
+ Cmd.CommandLine.push_back("-resource-dir=" + ResourceDir);
+ if (auto Error = index(std::move(Cmd), Storage))
+ log("Indexing {0} failed: {1}", File, std::move(Error));
+ },
+ std::move(*Cmd)),
+ ThreadPriority::Low);
}
}
-void BackgroundIndex::enqueueTask(Task T) {
+void BackgroundIndex::enqueueTask(Task T, ThreadPriority Priority) {
{
std::lock_guard<std::mutex> Lock(QueueMu);
- Queue.push_back(std::move(T));
+ auto I = Queue.end();
+ // We first store the tasks with Normal priority in the front of the queue.
+ // Then we store low priority tasks. Normal priority tasks are pretty rare,
+ // they should not grow beyond single-digit numbers, so it is OK to do
+ // linear search and insert after that.
+ if (Priority == ThreadPriority::Normal) {
+ I = llvm::find_if(Queue, [](const std::pair<Task, ThreadPriority> &Elem) {
+ return Elem.second == ThreadPriority::Low;
+ });
+ }
+ Queue.insert(I, {std::move(T), Priority});
}
QueueCV.notify_all();
}
diff --git a/clang-tools-extra/clangd/index/Background.h b/clang-tools-extra/clangd/index/Background.h
index e1eb3ccfd18..582dcc3827b 100644
--- a/clang-tools-extra/clangd/index/Background.h
+++ b/clang-tools-extra/clangd/index/Background.h
@@ -13,6 +13,7 @@
#include "Context.h"
#include "FSProvider.h"
#include "GlobalCompilationDatabase.h"
+#include "Threading.h"
#include "index/FileIndex.h"
#include "index/Index.h"
#include "index/Serialization.h"
@@ -110,14 +111,14 @@ private:
// queue management
using Task = std::function<void()>;
void run(); // Main loop executed by Thread. Runs tasks from Queue.
- void enqueueTask(Task T);
+ void enqueueTask(Task T, ThreadPriority Prioirty);
void enqueueLocked(tooling::CompileCommand Cmd,
BackgroundIndexStorage *IndexStorage);
std::mutex QueueMu;
unsigned NumActiveTasks = 0; // Only idle when queue is empty *and* no tasks.
std::condition_variable QueueCV;
bool ShouldStop = false;
- std::deque<Task> Queue;
+ std::deque<std::pair<Task, ThreadPriority>> Queue;
std::vector<std::thread> ThreadPool; // FIXME: Abstract this away.
GlobalCompilationDatabase::CommandChanged::Subscription CommandsChanged;
};
OpenPOWER on IntegriCloud