Reland "[heap] Reschedule concurrent marking tasks earlier"

This is a reland of b1c3ca2a71

Original change's description:
> [heap] Reschedule concurrent marking tasks earlier
> 
> Currently we reschedule concurrent marking tasks if all tasks finish.
> This is too conservative and we can improve performance by rescheduling
> finished tasks without waiting for all other tasks.
> 
> As a drive-by this also changes task_count_ to total_task_count_.
> 
> Change-Id: If0b3bd45ce6d52f6bcd0065dd8d3efe9ea84184a
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1789142
> Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Omer Katz <omerkatz@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#63593}

Change-Id: Id18bbb3cab85cd38bb7d2f21611825252ed4a1dc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1789288
Reviewed-by: Omer Katz <omerkatz@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63610}
This commit is contained in:
Ulan Degenbaev 2019-09-06 13:11:02 +02:00 committed by Commit Bot
parent 3d6b692b46
commit 098189473a
2 changed files with 21 additions and 17 deletions

View File

@ -864,8 +864,7 @@ void ConcurrentMarking::ScheduleTasks() {
DCHECK(FLAG_parallel_marking || FLAG_concurrent_marking);
DCHECK(!heap_->IsTearingDown());
base::MutexGuard guard(&pending_lock_);
DCHECK_EQ(0, pending_task_count_);
if (task_count_ == 0) {
if (total_task_count_ == 0) {
static const int num_cores =
V8::GetCurrentPlatform()->NumberOfWorkerThreads() + 1;
#if defined(V8_OS_MACOSX)
@ -873,15 +872,18 @@ void ConcurrentMarking::ScheduleTasks() {
// marking on competing hyper-threads (regresses Octane/Splay). As such,
// only use num_cores/2, leaving one of those for the main thread.
// TODO(ulan): Use all cores on Mac 10.12+.
task_count_ = Max(1, Min(kMaxTasks, (num_cores / 2) - 1));
total_task_count_ = Max(1, Min(kMaxTasks, (num_cores / 2) - 1));
#else // defined(OS_MACOSX)
// On other platforms use all logical cores, leaving one for the main
// thread.
task_count_ = Max(1, Min(kMaxTasks, num_cores - 1));
total_task_count_ = Max(1, Min(kMaxTasks, num_cores - 1));
#endif // defined(OS_MACOSX)
DCHECK_LE(total_task_count_, kMaxTasks);
// One task is for the main thread.
STATIC_ASSERT(kMaxTasks + 1 <= MarkingWorklist::kMaxNumTasks);
}
// Task id 0 is for the main thread.
for (int i = 1; i <= task_count_; i++) {
for (int i = 1; i <= total_task_count_; i++) {
if (!is_pending_[i]) {
if (FLAG_trace_concurrent_marking) {
heap_->isolate()->PrintWithTimestamp(
@ -899,7 +901,7 @@ void ConcurrentMarking::ScheduleTasks() {
V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task));
}
}
DCHECK_EQ(task_count_, pending_task_count_);
DCHECK_EQ(total_task_count_, pending_task_count_);
}
void ConcurrentMarking::RescheduleTasksIfNeeded() {
@ -907,11 +909,15 @@ void ConcurrentMarking::RescheduleTasksIfNeeded() {
if (heap_->IsTearingDown()) return;
{
base::MutexGuard guard(&pending_lock_);
if (pending_task_count_ > 0) return;
// The total task count is initialized in ScheduleTasks from
// NumberOfWorkerThreads of the platform.
if (total_task_count_ > 0 && pending_task_count_ == total_task_count_) {
return;
}
}
if (!shared_->IsGlobalPoolEmpty() ||
!weak_objects_->current_ephemerons.IsEmpty() ||
!weak_objects_->discovered_ephemerons.IsEmpty()) {
!weak_objects_->current_ephemerons.IsGlobalPoolEmpty() ||
!weak_objects_->discovered_ephemerons.IsGlobalPoolEmpty()) {
ScheduleTasks();
}
}
@ -925,7 +931,7 @@ bool ConcurrentMarking::Stop(StopRequest stop_request) {
if (stop_request != StopRequest::COMPLETE_TASKS_FOR_TESTING) {
CancelableTaskManager* task_manager =
heap_->isolate()->cancelable_task_manager();
for (int i = 1; i <= task_count_; i++) {
for (int i = 1; i <= total_task_count_; i++) {
if (is_pending_[i]) {
if (task_manager->TryAbort(cancelable_id_[i]) ==
TryAbortResult::kTaskAborted) {
@ -940,7 +946,7 @@ bool ConcurrentMarking::Stop(StopRequest stop_request) {
while (pending_task_count_ > 0) {
pending_condition_.Wait(&pending_lock_);
}
for (int i = 1; i <= task_count_; i++) {
for (int i = 1; i <= total_task_count_; i++) {
DCHECK(!is_pending_[i]);
}
return true;
@ -956,7 +962,7 @@ bool ConcurrentMarking::IsStopped() {
void ConcurrentMarking::FlushMemoryChunkData(
MajorNonAtomicMarkingState* marking_state) {
DCHECK_EQ(pending_task_count_, 0);
for (int i = 1; i <= task_count_; i++) {
for (int i = 1; i <= total_task_count_; i++) {
MemoryChunkDataMap& memory_chunk_data = task_state_[i].memory_chunk_data;
for (auto& pair : memory_chunk_data) {
// ClearLiveness sets the live bytes to zero.
@ -978,7 +984,7 @@ void ConcurrentMarking::FlushMemoryChunkData(
}
void ConcurrentMarking::ClearMemoryChunkData(MemoryChunk* chunk) {
for (int i = 1; i <= task_count_; i++) {
for (int i = 1; i <= total_task_count_; i++) {
auto it = task_state_[i].memory_chunk_data.find(chunk);
if (it != task_state_[i].memory_chunk_data.end()) {
it->second.live_bytes = 0;
@ -989,7 +995,7 @@ void ConcurrentMarking::ClearMemoryChunkData(MemoryChunk* chunk) {
size_t ConcurrentMarking::TotalMarkedBytes() {
size_t result = 0;
for (int i = 1; i <= task_count_; i++) {
for (int i = 1; i <= total_task_count_; i++) {
result +=
base::AsAtomicWord::Relaxed_Load<size_t>(&task_state_[i].marked_bytes);
}

View File

@ -86,8 +86,6 @@ class V8_EXPORT_PRIVATE ConcurrentMarking {
// scavenge and is going to be re-used.
void ClearMemoryChunkData(MemoryChunk* chunk);
int TaskCount() { return task_count_; }
// Checks if all threads are stopped.
bool IsStopped();
@ -124,7 +122,7 @@ class V8_EXPORT_PRIVATE ConcurrentMarking {
int pending_task_count_ = 0;
bool is_pending_[kMaxTasks + 1] = {};
CancelableTaskManager::Id cancelable_id_[kMaxTasks + 1] = {};
int task_count_ = 0;
int total_task_count_ = 0;
};
} // namespace internal