Commit d0ea6140 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm] Throttle the amount of unfinished work in async compilation

This CL does same changes as
https://chromium-review.googlesource.com/c/540763/, but for async
compilation instead of for parallel compilation. The biggest difference
is that for async compilation I start background tasks again when half
of the memory is free again and not when all the memory is free again.

Original description:

It is possible that the foreground task is unable to clear the
scheduled unfinished work, eventually leading to an OOM.

We use either code_range on 64 bit, or the capacity of the code space,
as a heuristic for how much memory to use for compilation.

The change avoids blocking the background threads while we're over the
memory threshold. This is to avoid starving the GC.

R=mtrofin@chromium.org

Change-Id: I7399e2474f72f6727e6e50176dd7ba95cdcd3238
Reviewed-on: https://chromium-review.googlesource.com/543477
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarMircea Trofin <mtrofin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46120}
parent baf95475
......@@ -57,6 +57,11 @@ bool ModuleCompiler::CodeGenerationSchedule::CanAcceptWork() const {
return (!throttle_ || allocated_memory_.Value() <= max_memory_);
}
bool ModuleCompiler::CodeGenerationSchedule::ShouldIncreaseWorkload() const {
// Half the memory is unused again, we can increase the workload again.
return (!throttle_ || allocated_memory_.Value() <= max_memory_ / 2);
}
std::unique_ptr<compiler::WasmCompilationUnit>
ModuleCompiler::CodeGenerationSchedule::GetNext() {
DCHECK(!IsEmpty());
......@@ -2015,14 +2020,18 @@ void AsyncCompileJob::DoSync(Args&&... args) {
StartForegroundTask();
}
void AsyncCompileJob::StartBackgroundTask() {
V8::GetCurrentPlatform()->CallOnBackgroundThread(
new CompileTask(this, false), v8::Platform::kShortRunningTask);
}
template <typename State, typename... Args>
void AsyncCompileJob::DoAsync(Args&&... args) {
step_.reset(new State(std::forward<Args>(args)...));
step_->job_ = this;
size_t end = step_->NumberOfBackgroundTasks();
for (size_t i = 0; i < end; ++i) {
V8::GetCurrentPlatform()->CallOnBackgroundThread(
new CompileTask(this, false), v8::Platform::kShortRunningTask);
StartBackgroundTask();
}
}
......@@ -2138,6 +2147,7 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
constexpr bool is_sync = true;
job_->compiler_.reset(
new ModuleCompiler(job_->isolate_, std::move(module_), !is_sync));
job_->compiler_->EnableThrottling();
DCHECK_LE(module->num_imported_functions, module->functions.size());
size_t num_functions =
......@@ -2181,15 +2191,26 @@ class AsyncCompileJob::ExecuteAndFinishCompilationUnits : public CompileStep {
};
TRACE_COMPILE("(3) Compiling...\n");
for (;;) {
while (job_->compiler_->CanAcceptWork()) {
if (failed_) break;
DisallowHandleAllocation no_handle;
DisallowHeapAllocation no_allocation;
if (!job_->compiler_->FetchAndExecuteCompilationUnit(
StartFinishCompilationUnit)) {
finished_ = true;
break;
}
}
stopped_tasks_.Increment(1);
}
void RestartCompilationTasks() {
size_t num_restarts = stopped_tasks_.Value();
stopped_tasks_.Decrement(num_restarts);
for (size_t i = 0; i < num_restarts; ++i) {
job_->StartBackgroundTask();
}
}
void RunInForeground() override {
......@@ -2206,6 +2227,10 @@ class AsyncCompileJob::ExecuteAndFinishCompilationUnits : public CompileStep {
double deadline = MonotonicallyIncreasingTimeInMs() + 1.0;
while (true) {
if (!finished_ && job_->compiler_->ShouldIncreaseWorkload()) {
RestartCompilationTasks();
}
int func_index = -1;
Handle<Code> result =
......@@ -2252,6 +2277,8 @@ class AsyncCompileJob::ExecuteAndFinishCompilationUnits : public CompileStep {
private:
std::atomic<bool> failed_{false};
std::atomic<bool> finished_{false};
base::AtomicNumber<size_t> stopped_tasks_{0};
};
//==========================================================================
......
......@@ -53,6 +53,8 @@ class ModuleCompiler {
bool CanAcceptWork() const;
bool ShouldIncreaseWorkload() const;
void EnableThrottling() { throttle_ = true; }
private:
......@@ -91,6 +93,14 @@ class ModuleCompiler {
bool GetNextUncompiledFunctionId(size_t* index);
void OnBackgroundTaskStopped();
void EnableThrottling() { executed_units_.EnableThrottling(); }
bool CanAcceptWork() const { return executed_units_.CanAcceptWork(); }
bool ShouldIncreaseWorkload() const {
return executed_units_.ShouldIncreaseWorkload();
}
size_t InitializeParallelCompilation(
const std::vector<WasmFunction>& functions, ModuleBytesEnv& module_env);
......@@ -321,6 +331,8 @@ class AsyncCompileJob {
void StartForegroundTask();
void StartBackgroundTask();
template <typename Task, typename... Args>
void DoAsync(Args&&... args);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment