Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Unified Diff: src/compiler-dispatcher/compiler-dispatcher.cc

Issue 2573493002: Use idle time to make progress on scheduled compilation jobs (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/compiler-dispatcher/compiler-dispatcher.cc
diff --git a/src/compiler-dispatcher/compiler-dispatcher.cc b/src/compiler-dispatcher/compiler-dispatcher.cc
index 8d503780cd5511b7af36cbbf865e6037277a5282..978aa1996d0b9fb972c433c8731ac5ec3efaf61a 100644
--- a/src/compiler-dispatcher/compiler-dispatcher.cc
+++ b/src/compiler-dispatcher/compiler-dispatcher.cc
@@ -4,6 +4,12 @@
#include "src/compiler-dispatcher/compiler-dispatcher.h"
+#include <queue>
+
+#include "include/v8-platform.h"
+#include "include/v8.h"
+#include "src/base/platform/time.h"
+#include "src/cancelable-task.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/objects-inl.h"
@@ -13,7 +19,11 @@ namespace internal {
namespace {
-bool DoNextStepOnMainThread(CompilerDispatcherJob* job) {
+enum class ExceptionHandling { kSwallow, kKeep };
+
+bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
+ ExceptionHandling exception_handling) {
+ v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
switch (job->status()) {
case CompileJobStatus::kInitial:
job->PrepareToParseOnMainThread();
@@ -44,6 +54,9 @@ bool DoNextStepOnMainThread(CompilerDispatcherJob* job) {
break;
}
+ if (exception_handling == ExceptionHandling::kKeep && try_catch.HasCaught()) {
+ try_catch.ReThrow();
+ }
marja 2016/12/13 09:09:01 Can we assert here that if the try catch has caugh
jochen (gone - plz use gerrit) 2016/12/15 13:54:34 done
return job->status() != CompileJobStatus::kFailed;
}
@@ -54,10 +67,37 @@ bool IsFinished(CompilerDispatcherJob* job) {
} // namespace
-CompilerDispatcher::CompilerDispatcher(Isolate* isolate, size_t max_stack_size)
+class CompilerDispatcher::IdleTask : public CancelableIdleTask {
+ public:
+ IdleTask(Isolate* isolate, CompilerDispatcher* dispatcher);
+ ~IdleTask() override;
+
+ // CancelableIdleTask implementation.
vogelheim 2016/12/12 17:51:32 I don't understand the comment. If the intention i
jochen (gone - plz use gerrit) 2016/12/12 20:28:25 it's a common pattern in chromium code as it has m
vogelheim 2016/12/13 09:40:33 Acknowledged.
+ void RunInternal(double deadline_in_seconds) override;
+
+ private:
+ CompilerDispatcher* dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdleTask);
+};
+
+CompilerDispatcher::IdleTask::IdleTask(Isolate* isolate,
+ CompilerDispatcher* dispatcher)
+ : CancelableIdleTask(isolate), dispatcher_(dispatcher) {}
+
+CompilerDispatcher::IdleTask::~IdleTask() {}
+
+void CompilerDispatcher::IdleTask::RunInternal(double deadline_in_seconds) {
+ dispatcher_->DoIdleWork(deadline_in_seconds);
+}
+
+CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform,
+ size_t max_stack_size)
: isolate_(isolate),
+ platform_(platform),
max_stack_size_(max_stack_size),
- tracer_(new CompilerDispatcherTracer(isolate_)) {}
+ tracer_(new CompilerDispatcherTracer(isolate_)),
+ idle_task_scheduled_(false) {}
CompilerDispatcher::~CompilerDispatcher() {}
@@ -75,6 +115,7 @@ bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
std::pair<int, int> key(Script::cast(function->script())->id(),
function->function_literal_id());
jobs_.insert(std::make_pair(key, std::move(job)));
+ ScheduleIdleTaskIfNeeded();
return true;
}
@@ -89,9 +130,11 @@ bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
// TODO(jochen): Check if there's an in-flight background task working on this
// job.
while (!IsFinished(job->second.get())) {
- DoNextStepOnMainThread(job->second.get());
+ DoNextStepOnMainThread(isolate_, job->second.get(),
+ ExceptionHandling::kKeep);
}
bool result = job->second->status() != CompileJobStatus::kFailed;
+ job->second->ResetOnMainThread();
jobs_.erase(job);
return result;
}
@@ -104,6 +147,7 @@ void CompilerDispatcher::Abort(Handle<SharedFunctionInfo> function,
// TODO(jochen): Check if there's an in-flight background task working on this
// job.
+ job->second->ResetOnMainThread();
jobs_.erase(job);
}
@@ -111,6 +155,9 @@ void CompilerDispatcher::AbortAll(BlockingBehavior blocking) {
USE(blocking);
// TODO(jochen): Check if there's an in-flight background task working on this
// job.
+ for (auto& kv : jobs_) {
+ kv.second->ResetOnMainThread();
+ }
jobs_.clear();
}
@@ -126,5 +173,69 @@ CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor(
return jobs_.end();
}
+void CompilerDispatcher::ScheduleIdleTaskIfNeeded() {
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
+ if (!platform_->IdleTasksEnabled(v8_isolate)) return;
+ if (idle_task_scheduled_) return;
+ if (jobs_.empty()) return;
+ idle_task_scheduled_ = true;
+ platform_->CallIdleOnForegroundThread(v8_isolate,
+ new IdleTask(isolate_, this));
+}
+
+void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
+ idle_task_scheduled_ = false;
marja 2016/12/13 09:09:01 Could you add assert(we're on the main thread) to
+
+ // Collect all candidates for running their respective next step during
+ // idle time and sort by how long they're likely to take.
marja 2016/12/13 09:09:01 Hmm, it looks inefficient to iterate through all i
+ auto cmp = [](const std::pair<double, JobMap::const_iterator>& a,
+ const std::pair<double, JobMap::const_iterator>& b) {
+ return a.first < b.first;
+ };
+ std::priority_queue<std::pair<double, JobMap::const_iterator>,
+ std::vector<std::pair<double, JobMap::const_iterator>>,
+ decltype(cmp)>
+ runtimes(cmp);
+ for (JobMap::const_iterator it = jobs_.begin(); it != jobs_.end(); ++it) {
+ if (IsFinished(it->second.get())) continue;
+ // TODO(jochen): Check if there's an in-flight background task working on
+ // this job.
+ runtimes.push(std::make_pair(
+ it->second->EstimateRuntimeOfNextStepInMs() /
vogelheim 2016/12/12 17:51:32 Every one of these will look the same lock, right?
jochen (gone - plz use gerrit) 2016/12/12 20:28:25 right, dunno how much of an issue that is?
+ static_cast<double>(base::Time::kMillisecondsPerSecond),
+ it));
+ }
+
+ for (double idle_time_in_seconds =
marja 2016/12/13 09:21:13 What if coming up with the priority queue takes so
+ deadline_in_seconds - platform_->MonotonicallyIncreasingTime();
+ idle_time_in_seconds > 0.0;
+ idle_time_in_seconds =
+ deadline_in_seconds - platform_->MonotonicallyIncreasingTime()) {
marja 2016/12/13 09:09:01 This loop is mildly confusing. Why not just: whi
+ // Skip jobs we can't do in the remaining time budget.
+ while (!runtimes.empty() && runtimes.top().first > idle_time_in_seconds) {
+ runtimes.pop();
vogelheim 2016/12/12 17:51:32 If runtimes is a priority queue by expected runtim
vogelheim 2016/12/12 17:51:32 [Not sure:] What happens when there is a job whose
jochen (gone - plz use gerrit) 2016/12/12 20:28:25 So far, the biggest task comes first. I guess I co
vogelheim 2016/12/13 09:40:33 Ah, I misread that and assumed we'd process tasks
+ }
+ if (runtimes.empty()) break;
+
+ JobMap::const_iterator job = runtimes.top().second;
+ runtimes.pop();
+ DoNextStepOnMainThread(isolate_, job->second.get(),
+ ExceptionHandling::kSwallow);
+
+ if (IsFinished(job->second.get())) {
+ job->second->ResetOnMainThread();
+ jobs_.erase(job);
+ continue;
+ }
+
+ // Put the job back on the queue in case there is time left.
+ runtimes.push(std::make_pair(
+ job->second->EstimateRuntimeOfNextStepInMs() /
+ static_cast<double>(base::Time::kMillisecondsPerSecond),
+ job));
vogelheim 2016/12/12 17:51:32 [Not sure:] It might make sense to store auto cu
jochen (gone - plz use gerrit) 2016/12/12 20:28:25 we still need the mutex, because after having made
vogelheim 2016/12/13 09:40:33 Ah. For my understanding: Why would the time esti
jochen (gone - plz use gerrit) 2016/12/15 13:54:34 in line 222 the job does one step, and i gets rein
+ }
+ ScheduleIdleTaskIfNeeded();
+}
+
} // namespace internal
} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698