Commit b1c3ca2a authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

[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: 's avatarOmer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63593}
parent 888eeccd
......@@ -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,7 +909,11 @@ 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() ||
......@@ -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);
}
......
......@@ -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
......
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