[compiler-dispatcher] Delete Jobs as BG work

Deleting / deallocating Jobs, along with everything they own (e.g.
PersistentHandles), can take a long time, especially if the allocator
isn't too friendly to deallocating on a different thread than where the
allocation happened.

Instead, enqueue Jobs for deletion as part of background processing,
with the hope that they end up being deallocated on the same thread as
they were allocated, and at the very least taking the deallocation time
off the main thread. The deletion queue is processed after the pending
background jobs are all processed, and counts as a single "background
job" as far as parallelism is concerned.

Bug: chromium:1275157
Change-Id: Ie7c3f725f7e510b4325e7590e60477338c478388
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3314835
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78307}
This commit is contained in:
Leszek Swirski 2021-12-08 16:10:07 +01:00 committed by V8 LUCI CQ
parent 67a59d803e
commit 85877e54b1
2 changed files with 30 additions and 3 deletions

View File

@ -357,6 +357,10 @@ void LazyCompileDispatcher::AbortAll() {
DeleteJob(job, lock);
}
finalizable_jobs_.clear();
for (Job* job : jobs_to_dispose_) {
delete job;
}
jobs_to_dispose_.clear();
DCHECK_EQ(all_jobs_.size(), 0);
num_jobs_for_background_ = 0;
@ -411,7 +415,7 @@ void LazyCompileDispatcher::DoBackgroundWork(JobDelegate* delegate) {
{
base::MutexGuard lock(&mutex_);
if (pending_background_jobs_.empty()) return;
if (pending_background_jobs_.empty()) break;
job = pending_background_jobs_.back();
pending_background_jobs_.pop_back();
DCHECK_EQ(job->state, Job::State::kPending);
@ -452,6 +456,20 @@ void LazyCompileDispatcher::DoBackgroundWork(JobDelegate* delegate) {
}
}
while (!delegate->ShouldYield()) {
Job* job = nullptr;
{
base::MutexGuard lock(&job_dispose_mutex_);
if (jobs_to_dispose_.empty()) break;
job = jobs_to_dispose_.back();
jobs_to_dispose_.pop_back();
if (jobs_to_dispose_.empty()) {
num_jobs_for_background_--;
}
}
delete job;
}
// Don't touch |this| anymore after this point, as it might have been
// deleted.
}
@ -537,7 +555,11 @@ void LazyCompileDispatcher::DeleteJob(Job* job, const base::MutexGuard&) {
#ifdef DEBUG
all_jobs_.erase(job);
#endif
delete job;
base::MutexGuard lock(&job_dispose_mutex_);
jobs_to_dispose_.push_back(job);
if (jobs_to_dispose_.size() == 1) {
num_jobs_for_background_++;
}
}
#ifdef DEBUG
@ -570,7 +592,8 @@ void LazyCompileDispatcher::VerifyBackgroundTaskCount(const base::MutexGuard&) {
CHECK_EQ(pending_background_jobs_.size(), pending_jobs);
CHECK_EQ(finalizable_jobs_.size(), finalizable_jobs);
CHECK_EQ(num_jobs_for_background_.load(), pending_jobs + running_jobs);
CHECK_EQ(num_jobs_for_background_.load(),
pending_jobs + running_jobs + (jobs_to_dispose_.empty() ? 0 : 1));
}
#endif

View File

@ -20,6 +20,7 @@
#include "src/common/globals.h"
#include "src/handles/maybe-handles.h"
#include "src/utils/identity-map.h"
#include "src/utils/locked-queue.h"
#include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck
namespace v8 {
@ -224,6 +225,9 @@ class V8_EXPORT_PRIVATE LazyCompileDispatcher {
Job* main_thread_blocking_on_job_;
base::ConditionVariable main_thread_blocking_signal_;
mutable base::Mutex job_dispose_mutex_;
std::vector<Job*> jobs_to_dispose_;
// Test support.
base::AtomicValue<bool> block_for_testing_;
base::Semaphore semaphore_for_testing_;