Skip to content

Commit eef37d0

Browse files
joyeecheungaduh95
authored andcommitted
src: add more debug logs and comments in NodePlatform
PR-URL: #58047 Refs: #47452 Refs: #54918 Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
1 parent bef06b1 commit eef37d0

File tree

3 files changed

+154
-15
lines changed

3 files changed

+154
-15
lines changed

src/debug_utils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ void NODE_EXTERN_PRIVATE FWrite(FILE* file, const std::string& str);
5555
V(MKSNAPSHOT) \
5656
V(SNAPSHOT_SERDES) \
5757
V(PERMISSION_MODEL) \
58+
V(PLATFORM_MINIMAL) \
59+
V(PLATFORM_VERBOSE) \
5860
V(QUIC)
5961

6062
enum class DebugCategory : unsigned int {

src/node_platform.cc

Lines changed: 129 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ using v8::Isolate;
1313
using v8::Object;
1414
using v8::Platform;
1515
using v8::Task;
16+
using v8::TaskPriority;
1617

1718
namespace {
1819

@@ -22,8 +23,31 @@ struct PlatformWorkerData {
2223
ConditionVariable* platform_workers_ready;
2324
int* pending_platform_workers;
2425
int id;
26+
PlatformDebugLogLevel debug_log_level;
2527
};
2628

29+
const char* GetTaskPriorityName(TaskPriority priority) {
30+
switch (priority) {
31+
case TaskPriority::kUserBlocking:
32+
return "UserBlocking";
33+
case TaskPriority::kUserVisible:
34+
return "UserVisible";
35+
case TaskPriority::kBestEffort:
36+
return "BestEffort";
37+
default:
38+
return "Unknown";
39+
}
40+
}
41+
42+
static void PrintSourceLocation(const v8::SourceLocation& location) {
43+
auto loc = location.ToString();
44+
if (!loc.empty()) {
45+
fprintf(stderr, " %s\n", loc.c_str());
46+
} else {
47+
fprintf(stderr, " <no location>\n");
48+
}
49+
}
50+
2751
static void PlatformWorkerThread(void* data) {
2852
std::unique_ptr<PlatformWorkerData>
2953
worker_data(static_cast<PlatformWorkerData*>(data));
@@ -39,8 +63,18 @@ static void PlatformWorkerThread(void* data) {
3963
worker_data->platform_workers_ready->Signal(lock);
4064
}
4165

66+
bool debug_log_enabled =
67+
worker_data->debug_log_level != PlatformDebugLogLevel::kNone;
68+
int id = worker_data->id;
4269
while (std::unique_ptr<Task> task =
4370
pending_worker_tasks->Lock().BlockingPop()) {
71+
if (debug_log_enabled) {
72+
fprintf(stderr,
73+
"\nPlatformWorkerThread %d running task %p\n",
74+
id,
75+
task.get());
76+
fflush(stderr);
77+
}
4478
task->Run();
4579
pending_worker_tasks->Lock().NotifyOfCompletion();
4680
}
@@ -74,6 +108,12 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
74108

75109
void PostDelayedTask(std::unique_ptr<Task> task, double delay_in_seconds) {
76110
auto locked = tasks_.Lock();
111+
112+
// The delayed task scheuler is on is own thread with its own loop that
113+
// runs the timers for the scheduled tasks to pop the original task back
114+
// into the the worker task queue. This first pushes the tasks that
115+
// schedules the timers into the local task queue that will be flushed
116+
// by the local event loop.
77117
locked.Push(std::make_unique<ScheduleTask>(
78118
this, std::move(task), delay_in_seconds));
79119
uv_async_send(&flush_tasks_);
@@ -108,6 +148,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
108148
while (!tasks_to_run.empty()) {
109149
std::unique_ptr<Task> task = std::move(tasks_to_run.front());
110150
tasks_to_run.pop();
151+
// This runs either the ScheduleTasks that scheduels the timers to
152+
// pop the tasks back into the worker task runner queue, or the
153+
// or the StopTasks to stop the timers and drop all the pending tasks.
111154
task->Run();
112155
}
113156
}
@@ -135,9 +178,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
135178
ScheduleTask(DelayedTaskScheduler* scheduler,
136179
std::unique_ptr<Task> task,
137180
double delay_in_seconds)
138-
: scheduler_(scheduler),
139-
task_(std::move(task)),
140-
delay_in_seconds_(delay_in_seconds) {}
181+
: scheduler_(scheduler),
182+
task_(std::move(task)),
183+
delay_in_seconds_(delay_in_seconds) {}
141184

142185
void Run() override {
143186
uint64_t delay_millis = llround(delay_in_seconds_ * 1000);
@@ -172,15 +215,21 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
172215
}
173216

174217
uv_sem_t ready_;
218+
// Task queue in the worker thread task runner, we push the delayed task back
219+
// to it when the timer expires.
175220
TaskQueue<Task>* pending_worker_tasks_;
176221

222+
// Locally scheduled tasks to be poped into the worker task runner queue.
223+
// It is flushed whenever the next closest timer expires.
177224
TaskQueue<Task> tasks_;
178225
uv_loop_t loop_;
179226
uv_async_t flush_tasks_;
180227
std::unordered_set<uv_timer_t*> timers_;
181228
};
182229

183-
WorkerThreadsTaskRunner::WorkerThreadsTaskRunner(int thread_pool_size) {
230+
WorkerThreadsTaskRunner::WorkerThreadsTaskRunner(
231+
int thread_pool_size, PlatformDebugLogLevel debug_log_level)
232+
: debug_log_level_(debug_log_level) {
184233
Mutex platform_workers_mutex;
185234
ConditionVariable platform_workers_ready;
186235

@@ -192,10 +241,13 @@ WorkerThreadsTaskRunner::WorkerThreadsTaskRunner(int thread_pool_size) {
192241
threads_.push_back(delayed_task_scheduler_->Start());
193242

194243
for (int i = 0; i < thread_pool_size; i++) {
195-
PlatformWorkerData* worker_data = new PlatformWorkerData{
196-
&pending_worker_tasks_, &platform_workers_mutex,
197-
&platform_workers_ready, &pending_platform_workers, i
198-
};
244+
PlatformWorkerData* worker_data =
245+
new PlatformWorkerData{&pending_worker_tasks_,
246+
&platform_workers_mutex,
247+
&platform_workers_ready,
248+
&pending_platform_workers,
249+
i,
250+
debug_log_level_};
199251
std::unique_ptr<uv_thread_t> t { new uv_thread_t() };
200252
if (uv_thread_create(t.get(), PlatformWorkerThread,
201253
worker_data) != 0) {
@@ -237,8 +289,8 @@ int WorkerThreadsTaskRunner::NumberOfWorkerThreads() const {
237289
}
238290

239291
PerIsolatePlatformData::PerIsolatePlatformData(
240-
Isolate* isolate, uv_loop_t* loop)
241-
: isolate_(isolate), loop_(loop) {
292+
Isolate* isolate, uv_loop_t* loop, PlatformDebugLogLevel debug_log_level)
293+
: isolate_(isolate), loop_(loop), debug_log_level_(debug_log_level) {
242294
flush_tasks_ = new uv_async_t();
243295
CHECK_EQ(0, uv_async_init(loop, flush_tasks_, FlushTasks));
244296
flush_tasks_->data = static_cast<void*>(this);
@@ -264,6 +316,14 @@ void PerIsolatePlatformData::PostTask(std::unique_ptr<Task> task) {
264316
// the foreground task runner is being cleaned up by Shutdown(). In that
265317
// case, make sure we wait until the shutdown is completed (which leads
266318
// to flush_tasks_ == nullptr, and the task will be discarded).
319+
if (debug_log_level_ != PlatformDebugLogLevel::kNone) {
320+
fprintf(stderr, "\nPerIsolatePlatformData::PostTaskImpl %p", task.get());
321+
if (debug_log_level_ == PlatformDebugLogLevel::kVerbose) {
322+
DumpNativeBacktrace(stderr);
323+
}
324+
fflush(stderr);
325+
}
326+
267327
auto locked = foreground_tasks_.Lock();
268328
if (flush_tasks_ == nullptr) return;
269329
locked.Push(std::move(task));
@@ -272,6 +332,17 @@ void PerIsolatePlatformData::PostTask(std::unique_ptr<Task> task) {
272332

273333
void PerIsolatePlatformData::PostDelayedTask(
274334
std::unique_ptr<Task> task, double delay_in_seconds) {
335+
if (debug_log_level_ != PlatformDebugLogLevel::kNone) {
336+
fprintf(stderr,
337+
"\nPerIsolatePlatformData::PostDelayedTaskImpl %p %f",
338+
task.get(),
339+
delay_in_seconds);
340+
if (debug_log_level_ == PlatformDebugLogLevel::kVerbose) {
341+
DumpNativeBacktrace(stderr);
342+
}
343+
fflush(stderr);
344+
}
345+
275346
auto locked = foreground_delayed_tasks_.Lock();
276347
if (flush_tasks_ == nullptr) return;
277348
std::unique_ptr<DelayedTask> delayed(new DelayedTask());
@@ -339,6 +410,16 @@ void PerIsolatePlatformData::DecreaseHandleCount() {
339410
NodePlatform::NodePlatform(int thread_pool_size,
340411
v8::TracingController* tracing_controller,
341412
v8::PageAllocator* page_allocator) {
413+
if (per_process::enabled_debug_list.enabled(
414+
DebugCategory::PLATFORM_VERBOSE)) {
415+
debug_log_level_ = PlatformDebugLogLevel::kVerbose;
416+
} else if (per_process::enabled_debug_list.enabled(
417+
DebugCategory::PLATFORM_MINIMAL)) {
418+
debug_log_level_ = PlatformDebugLogLevel::kMinimal;
419+
} else {
420+
debug_log_level_ = PlatformDebugLogLevel::kNone;
421+
}
422+
342423
if (tracing_controller != nullptr) {
343424
tracing_controller_ = tracing_controller;
344425
} else {
@@ -355,8 +436,8 @@ NodePlatform::NodePlatform(int thread_pool_size,
355436
DCHECK_EQ(GetTracingController(), tracing_controller_);
356437

357438
thread_pool_size = GetActualThreadPoolSize(thread_pool_size);
358-
worker_thread_task_runner_ =
359-
std::make_shared<WorkerThreadsTaskRunner>(thread_pool_size);
439+
worker_thread_task_runner_ = std::make_shared<WorkerThreadsTaskRunner>(
440+
thread_pool_size, debug_log_level_);
360441
}
361442

362443
NodePlatform::~NodePlatform() {
@@ -365,7 +446,8 @@ NodePlatform::~NodePlatform() {
365446

366447
void NodePlatform::RegisterIsolate(Isolate* isolate, uv_loop_t* loop) {
367448
Mutex::ScopedLock lock(per_isolate_mutex_);
368-
auto delegate = std::make_shared<PerIsolatePlatformData>(isolate, loop);
449+
auto delegate =
450+
std::make_shared<PerIsolatePlatformData>(isolate, loop, debug_log_level_);
369451
IsolatePlatformDelegate* ptr = delegate.get();
370452
auto insertion = per_isolate_.emplace(
371453
isolate,
@@ -520,6 +602,17 @@ void NodePlatform::PostTaskOnWorkerThreadImpl(
520602
v8::TaskPriority priority,
521603
std::unique_ptr<v8::Task> task,
522604
const v8::SourceLocation& location) {
605+
if (debug_log_level_ != PlatformDebugLogLevel::kNone) {
606+
fprintf(stderr,
607+
"\nNodePlatform::PostTaskOnWorkerThreadImpl %s %p",
608+
GetTaskPriorityName(priority),
609+
task.get());
610+
PrintSourceLocation(location);
611+
if (debug_log_level_ == PlatformDebugLogLevel::kVerbose) {
612+
DumpNativeBacktrace(stderr);
613+
}
614+
fflush(stderr);
615+
}
523616
worker_thread_task_runner_->PostTask(std::move(task));
524617
}
525618

@@ -528,6 +621,18 @@ void NodePlatform::PostDelayedTaskOnWorkerThreadImpl(
528621
std::unique_ptr<v8::Task> task,
529622
double delay_in_seconds,
530623
const v8::SourceLocation& location) {
624+
if (debug_log_level_ != PlatformDebugLogLevel::kNone) {
625+
fprintf(stderr,
626+
"\nNodePlatform::PostDelayedTaskOnWorkerThreadImpl %s %p %f",
627+
GetTaskPriorityName(priority),
628+
task.get(),
629+
delay_in_seconds);
630+
PrintSourceLocation(location);
631+
if (debug_log_level_ == PlatformDebugLogLevel::kVerbose) {
632+
DumpNativeBacktrace(stderr);
633+
}
634+
fflush(stderr);
635+
}
531636
worker_thread_task_runner_->PostDelayedTask(std::move(task),
532637
delay_in_seconds);
533638
}
@@ -557,6 +662,17 @@ std::unique_ptr<v8::JobHandle> NodePlatform::CreateJobImpl(
557662
v8::TaskPriority priority,
558663
std::unique_ptr<v8::JobTask> job_task,
559664
const v8::SourceLocation& location) {
665+
if (debug_log_level_ != PlatformDebugLogLevel::kNone) {
666+
fprintf(stderr,
667+
"\nNodePlatform::CreateJobImpl %s %p",
668+
GetTaskPriorityName(priority),
669+
job_task.get());
670+
PrintSourceLocation(location);
671+
if (debug_log_level_ == PlatformDebugLogLevel::kVerbose) {
672+
DumpNativeBacktrace(stderr);
673+
}
674+
fflush(stderr);
675+
}
560676
return v8::platform::NewDefaultJobHandle(
561677
this, priority, std::move(job_task), NumberOfWorkerThreads());
562678
}

src/node_platform.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,22 @@ struct DelayedTask {
6161
std::shared_ptr<PerIsolatePlatformData> platform_data;
6262
};
6363

64+
enum class PlatformDebugLogLevel {
65+
kNone = 0,
66+
kMinimal = 1,
67+
kVerbose = 2,
68+
};
69+
6470
// This acts as the foreground task runner for a given Isolate.
6571
class PerIsolatePlatformData :
6672
public IsolatePlatformDelegate,
6773
public v8::TaskRunner,
6874
public std::enable_shared_from_this<PerIsolatePlatformData> {
6975
public:
70-
PerIsolatePlatformData(v8::Isolate* isolate, uv_loop_t* loop);
76+
PerIsolatePlatformData(
77+
v8::Isolate* isolate,
78+
uv_loop_t* loop,
79+
PlatformDebugLogLevel debug_log_level = PlatformDebugLogLevel::kNone);
7180
~PerIsolatePlatformData() override;
7281

7382
std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner() override;
@@ -126,12 +135,14 @@ class PerIsolatePlatformData :
126135
typedef std::unique_ptr<DelayedTask, void(*)(DelayedTask*)>
127136
DelayedTaskPointer;
128137
std::vector<DelayedTaskPointer> scheduled_delayed_tasks_;
138+
PlatformDebugLogLevel debug_log_level_ = PlatformDebugLogLevel::kNone;
129139
};
130140

131141
// This acts as the single worker thread task runner for all Isolates.
132142
class WorkerThreadsTaskRunner {
133143
public:
134-
explicit WorkerThreadsTaskRunner(int thread_pool_size);
144+
explicit WorkerThreadsTaskRunner(int thread_pool_size,
145+
PlatformDebugLogLevel debug_log_level);
135146

136147
void PostTask(std::unique_ptr<v8::Task> task);
137148
void PostDelayedTask(std::unique_ptr<v8::Task> task,
@@ -143,12 +154,21 @@ class WorkerThreadsTaskRunner {
143154
int NumberOfWorkerThreads() const;
144155

145156
private:
157+
// A queue shared by all threads. The consumers are the worker threads which
158+
// take tasks from it to run in PlatformWorkerThread(). The producers can be
159+
// any thread. Both the foreground thread and the worker threads can push
160+
// tasks into the queue via v8::Platform::PostTaskOnWorkerThread() which
161+
// eventually calls PostTask() on this class. When any thread calls
162+
// v8::Platform::PostDelayedTaskOnWorkerThread(), the DelayedTaskScheduler
163+
// thread will schedule a timer that pushes the delayed tasks back into this
164+
// queue when the timer expires.
146165
TaskQueue<v8::Task> pending_worker_tasks_;
147166

148167
class DelayedTaskScheduler;
149168
std::unique_ptr<DelayedTaskScheduler> delayed_task_scheduler_;
150169

151170
std::vector<std::unique_ptr<uv_thread_t>> threads_;
171+
PlatformDebugLogLevel debug_log_level_ = PlatformDebugLogLevel::kNone;
152172
};
153173

154174
class NodePlatform : public MultiIsolatePlatform {
@@ -208,6 +228,7 @@ class NodePlatform : public MultiIsolatePlatform {
208228
v8::PageAllocator* page_allocator_;
209229
std::shared_ptr<WorkerThreadsTaskRunner> worker_thread_task_runner_;
210230
bool has_shut_down_ = false;
231+
PlatformDebugLogLevel debug_log_level_ = PlatformDebugLogLevel::kNone;
211232
};
212233

213234
} // namespace node

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy