Commit 0ecdae59 authored by JianxiaoLuIntel's avatar JianxiaoLuIntel Committed by V8 LUCI CQ

[heap] Expose max worker number of concurrent marking as a runtime flag

See details at https://groups.google.com/g/v8-dev/c/H3YXXKoauLI

Change-Id: Ibe255e95bfd1d09a115eb04d6cbfcca7a671d900
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3756729Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Jianxiao Lu <jianxiao.lu@intel.com>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81709}
parent 6c4b2e0e
......@@ -1315,6 +1315,9 @@ DEFINE_BOOL(write_protect_code_memory, true, "write protect code memory")
#endif
DEFINE_BOOL(concurrent_marking, V8_CONCURRENT_MARKING_BOOL,
"use concurrent marking")
DEFINE_INT(
concurrent_marking_max_worker_num, 7,
"max worker number of concurrent marking, 0 for NumberOfWorkerThreads")
DEFINE_BOOL(concurrent_array_buffer_sweeping, true,
"concurrently sweep array buffers")
DEFINE_BOOL(stress_concurrent_allocation, false,
......
......@@ -441,6 +441,17 @@ ConcurrentMarking::ConcurrentMarking(Heap* heap,
// Concurrent marking requires atomic object field writes.
CHECK(!FLAG_concurrent_marking);
#endif
int max_tasks;
if (FLAG_concurrent_marking_max_worker_num == 0) {
max_tasks = V8::GetCurrentPlatform()->NumberOfWorkerThreads();
} else {
max_tasks = FLAG_concurrent_marking_max_worker_num;
}
task_state_.reserve(max_tasks + 1);
for (int i = 0; i <= max_tasks; ++i) {
task_state_.emplace_back(std::make_unique<TaskState>());
}
}
void ConcurrentMarking::Run(JobDelegate* delegate,
......@@ -450,7 +461,7 @@ void ConcurrentMarking::Run(JobDelegate* delegate,
size_t kBytesUntilInterruptCheck = 64 * KB;
int kObjectsUntilInterruptCheck = 1000;
uint8_t task_id = delegate->GetTaskId() + 1;
TaskState* task_state = &task_state_[task_id];
TaskState* task_state = task_state_[task_id].get();
auto* cpp_heap = CppHeap::From(heap_->cpp_heap());
MarkingWorklists::Local local_marking_worklists(
marking_worklists_, cpp_heap
......@@ -577,7 +588,7 @@ size_t ConcurrentMarking::GetMaxConcurrency(size_t worker_count) {
for (auto& worklist : marking_worklists_->context_worklists())
marking_items += worklist.worklist->Size();
return std::min<size_t>(
kMaxTasks,
task_state_.size() - 1,
worker_count +
std::max<size_t>({marking_items,
weak_objects_->discovered_ephemerons.Size(),
......@@ -637,17 +648,17 @@ bool ConcurrentMarking::IsStopped() {
void ConcurrentMarking::FlushNativeContexts(NativeContextStats* main_stats) {
DCHECK(!job_handle_ || !job_handle_->IsValid());
for (int i = 1; i <= kMaxTasks; i++) {
main_stats->Merge(task_state_[i].native_context_stats);
task_state_[i].native_context_stats.Clear();
for (size_t i = 1; i < task_state_.size(); i++) {
main_stats->Merge(task_state_[i]->native_context_stats);
task_state_[i]->native_context_stats.Clear();
}
}
void ConcurrentMarking::FlushMemoryChunkData(
NonAtomicMarkingState* marking_state) {
DCHECK(!job_handle_ || !job_handle_->IsValid());
for (int i = 1; i <= kMaxTasks; i++) {
MemoryChunkDataMap& memory_chunk_data = task_state_[i].memory_chunk_data;
for (size_t i = 1; i < task_state_.size(); i++) {
MemoryChunkDataMap& memory_chunk_data = task_state_[i]->memory_chunk_data;
for (auto& pair : memory_chunk_data) {
// ClearLiveness sets the live bytes to zero.
// Pages with zero live bytes might be already unmapped.
......@@ -662,16 +673,16 @@ void ConcurrentMarking::FlushMemoryChunkData(
}
}
memory_chunk_data.clear();
task_state_[i].marked_bytes = 0;
task_state_[i]->marked_bytes = 0;
}
total_marked_bytes_ = 0;
}
void ConcurrentMarking::ClearMemoryChunkData(MemoryChunk* chunk) {
DCHECK(!job_handle_ || !job_handle_->IsValid());
for (int i = 1; i <= kMaxTasks; i++) {
auto it = task_state_[i].memory_chunk_data.find(chunk);
if (it != task_state_[i].memory_chunk_data.end()) {
for (size_t i = 1; i < task_state_.size(); 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;
it->second.typed_slots.reset();
}
......@@ -680,9 +691,9 @@ void ConcurrentMarking::ClearMemoryChunkData(MemoryChunk* chunk) {
size_t ConcurrentMarking::TotalMarkedBytes() {
size_t result = 0;
for (int i = 1; i <= kMaxTasks; i++) {
for (size_t i = 1; i < task_state_.size(); i++) {
result +=
base::AsAtomicWord::Relaxed_Load<size_t>(&task_state_[i].marked_bytes);
base::AsAtomicWord::Relaxed_Load<size_t>(&task_state_[i]->marked_bytes);
}
result += total_marked_bytes_;
return result;
......
......@@ -53,11 +53,6 @@ class V8_EXPORT_PRIVATE ConcurrentMarking {
const bool resume_on_exit_;
};
// TODO(gab): The only thing that prevents this being above 7 is
// Worklist::kMaxNumTasks being maxed at 8 (concurrent marking doesn't use
// task 0, reserved for the main thread).
static constexpr int kMaxTasks = 7;
ConcurrentMarking(Heap* heap, MarkingWorklists* marking_worklists,
WeakObjects* weak_objects);
......@@ -114,7 +109,7 @@ class V8_EXPORT_PRIVATE ConcurrentMarking {
Heap* const heap_;
MarkingWorklists* const marking_worklists_;
WeakObjects* const weak_objects_;
TaskState task_state_[kMaxTasks + 1];
std::vector<std::unique_ptr<TaskState>> task_state_;
std::atomic<size_t> total_marked_bytes_{0};
std::atomic<bool> another_ephemeron_iteration_{false};
};
......
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