From 11d6a2693bb9fe5cb39d1a61b51ffb0d880994b6 Mon Sep 17 00:00:00 2001 From: hyj1991 Date: Wed, 12 Oct 2022 11:23:44 +0800 Subject: [PATCH 1/3] refactor: replace dump actions static storages with EnvironmentData --- src/commands/dump.cc | 161 +++++++++++++++++++++-------------------- src/environment_data.h | 14 ++++ 2 files changed, 96 insertions(+), 79 deletions(-) diff --git a/src/commands/dump.cc b/src/commands/dump.cc index e4b5598..803db18 100644 --- a/src/commands/dump.cc +++ b/src/commands/dump.cc @@ -40,19 +40,6 @@ const DependentMap dependent_map = { {STOP_SAMPLING_HEAP_PROFILING, START_SAMPLING_HEAP_PROFILING}, {STOP_GC_PROFILING, START_GC_PROFILING}}; -/** - * Per-process slots. Diagnostics action can not be performed concurrently. - */ -namespace { -uv_thread_t uv_profiling_callback_thread; -ActionMap action_map; -std::string cpuprofile_filepath = ""; -std::string sampling_heapprofile_filepath = ""; -std::string heapsnapshot_filepath = ""; -std::string gcprofile_filepath = ""; -std::string node_report_filepath = ""; -std::string coredump_filepath = ""; - string Action2String(DumpAction action) { string name = ""; switch (action) { @@ -90,16 +77,17 @@ string Action2String(DumpAction action) { return name; } -void ActionRunning(DumpAction action, XpfError& err) { +void ActionRunning(ActionMap action_map, DumpAction action, XpfError& err) { if (action_map.find(action) != action_map.end()) { err = XpfError::Failure("%s is running.", Action2String(action).c_str()); } } -void ConflictActionRunning(DumpAction action, XpfError& err) { +void ConflictActionRunning(ActionMap action_map, DumpAction action, + XpfError& err) { if (conflict_map.find(action) != conflict_map.end()) { for (DumpAction confilct : conflict_map.at(action)) { - ActionRunning(confilct, err); + ActionRunning(action_map, confilct, err); if (err.Fail()) { err = XpfError::Failure( "%s conflict action %s is running, please wait for done.", @@ -110,10 +98,11 @@ void ConflictActionRunning(DumpAction action, XpfError& err) { } } -void DependentActionRunning(DumpAction action, XpfError& err) { +void DependentActionRunning(ActionMap action_map, DumpAction action, + XpfError& err) { if (dependent_map.find(action) != dependent_map.end()) { DumpAction dependent_action = dependent_map.at(action); - ActionRunning(dependent_action, err); + ActionRunning(action_map, dependent_action, err); if (err.Success()) err = XpfError::Failure("%s dependent action %s is not running.", Action2String(action).c_str(), @@ -124,8 +113,8 @@ void DependentActionRunning(DumpAction action, XpfError& err) { } template -T* GetProfilingData(void* data, string notify_type, string unique_key) { - Isolate* isolate = Isolate::GetCurrent(); +T* GetProfilingData(Isolate* isolate, void* data, string notify_type, + string unique_key) { EnvironmentData* env_data = EnvironmentData::GetCurrent(isolate); T* dump_data = static_cast(data); DebugT(module_type, env_data->thread_id(), "<%s> %s action start.", @@ -133,16 +122,14 @@ T* GetProfilingData(void* data, string notify_type, string unique_key) { return dump_data; } -void AfterDumpFile(string& filepath, string notify_type, string unique_key) { - Isolate* isolate = Isolate::GetCurrent(); +void AfterDumpFile(Isolate* isolate, string& filepath, string notify_type, + string unique_key) { EnvironmentData* env_data = EnvironmentData::GetCurrent(isolate); DebugT(module_type, env_data->thread_id(), "<%s> %s dump file: %s.", notify_type.c_str(), unique_key.c_str(), filepath.c_str()); filepath = ""; } -} // namespace - #define CLEAR_DATA \ DebugT(module_type, env_data->thread_id(), "<%s> %s dump_data cleared.", \ notify_type.c_str(), unique_key.c_str()); \ @@ -161,7 +148,11 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { BaseDumpData* dump_data = static_cast(data); string traceid = dump_data->traceid; DumpAction action = dump_data->action; + EnvironmentData* env_data = EnvironmentData::GetCurrent(isolate); + if (env_data == nullptr) { + return; + } // check transaction has been done XpfError err; @@ -172,69 +163,80 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { notify_type.c_str(), unique_key.c_str()); // check conflict action running - CHECK_ERR(ConflictActionRunning(action, err)) + CHECK_ERR(ConflictActionRunning(env_data->action_map, action, err)) // check dependent action running - CHECK_ERR(DependentActionRunning(action, err)) + CHECK_ERR(DependentActionRunning(env_data->action_map, action, err)) // start run action switch (action) { case START_CPU_PROFILING: { - CpuProfilerDumpData* tmp = - GetProfilingData(data, notify_type, unique_key); + CpuProfilerDumpData* tmp = GetProfilingData( + isolate, data, notify_type, unique_key); CpuProfiler::StartProfiling(isolate, tmp->title); break; } case STOP_CPU_PROFILING: { dump_data->run_once = true; CpuProfilerDumpData* tmp = static_cast(data); - CpuProfiler::StopProfiling(isolate, tmp->title, cpuprofile_filepath); - AfterDumpFile(cpuprofile_filepath, notify_type, unique_key); - action_map.erase(START_CPU_PROFILING); - action_map.erase(STOP_CPU_PROFILING); + CpuProfiler::StopProfiling(isolate, tmp->title, + env_data->cpuprofile_filepath); + AfterDumpFile(isolate, env_data->cpuprofile_filepath, notify_type, + unique_key); + env_data->action_map.erase(START_CPU_PROFILING); + env_data->action_map.erase(STOP_CPU_PROFILING); break; } case HEAPDUMP: { - HeapProfiler::TakeSnapshot(isolate, heapsnapshot_filepath); - AfterDumpFile(heapsnapshot_filepath, notify_type, unique_key); - action_map.erase(HEAPDUMP); + HeapProfiler::TakeSnapshot(isolate, env_data->heapsnapshot_filepath); + AfterDumpFile(isolate, env_data->heapsnapshot_filepath, notify_type, + unique_key); + env_data->action_map.erase(HEAPDUMP); break; } case START_SAMPLING_HEAP_PROFILING: { + GetProfilingData(isolate, data, notify_type, + unique_key); SamplingHeapProfiler::StartSamplingHeapProfiling(isolate); break; } case STOP_SAMPLING_HEAP_PROFILING: { dump_data->run_once = true; SamplingHeapProfiler::StopSamplingHeapProfiling( - isolate, sampling_heapprofile_filepath); - AfterDumpFile(sampling_heapprofile_filepath, notify_type, unique_key); - action_map.erase(START_SAMPLING_HEAP_PROFILING); - action_map.erase(STOP_SAMPLING_HEAP_PROFILING); + isolate, env_data->sampling_heapprofile_filepath); + AfterDumpFile(isolate, env_data->sampling_heapprofile_filepath, + notify_type, unique_key); + env_data->action_map.erase(START_SAMPLING_HEAP_PROFILING); + env_data->action_map.erase(STOP_SAMPLING_HEAP_PROFILING); break; } case START_GC_PROFILING: { - GcProfiler::StartGCProfiling(isolate, gcprofile_filepath); + GetProfilingData(isolate, data, notify_type, + unique_key); + GcProfiler::StartGCProfiling(isolate, env_data->gcprofile_filepath); break; } case STOP_GC_PROFILING: { dump_data->run_once = true; GcProfiler::StopGCProfiling(isolate); - AfterDumpFile(gcprofile_filepath, notify_type, unique_key); - action_map.erase(START_GC_PROFILING); - action_map.erase(STOP_GC_PROFILING); + AfterDumpFile(isolate, env_data->gcprofile_filepath, notify_type, + unique_key); + env_data->action_map.erase(START_GC_PROFILING); + env_data->action_map.erase(STOP_GC_PROFILING); break; } case NODE_REPORT: { - NodeReport::GetNodeReport(isolate, node_report_filepath); - AfterDumpFile(node_report_filepath, notify_type, unique_key); - action_map.erase(NODE_REPORT); + NodeReport::GetNodeReport(isolate, env_data->node_report_filepath); + AfterDumpFile(isolate, env_data->node_report_filepath, notify_type, + unique_key); + env_data->action_map.erase(NODE_REPORT); break; } case COREDUMP: { - Coredumper::WriteCoredump(coredump_filepath); - AfterDumpFile(coredump_filepath, notify_type, unique_key); - action_map.erase(COREDUMP); + Coredumper::WriteCoredump(env_data->coredump_filepath); + AfterDumpFile(isolate, env_data->coredump_filepath, notify_type, + unique_key); + env_data->action_map.erase(COREDUMP); break; } default: @@ -329,18 +331,7 @@ static json DoDumpAction(json command, string prefix, string ext, T* data, CHECK_ERR(ThreadId thread_id = GetJsonValue(command, "thread_id", err)) - // check action running - CHECK_ERR(ActionRunning(action, err)) - - // check conflict action running - CHECK_ERR(ConflictActionRunning(action, err)) - - // check dependent action running - CHECK_ERR(DependentActionRunning(action, err)) - - // set action running flag - action_map.insert(make_pair(action, true)); - + // get environment EnvironmentRegistry* registry = ProcessData::Get()->environment_registry(); EnvironmentRegistry::NoExitScope scope(registry); EnvironmentData* env_data = registry->Get(thread_id); @@ -349,44 +340,56 @@ static json DoDumpAction(json command, string prefix, string ext, T* data, return result; } + // check action running + CHECK_ERR(ActionRunning(env_data->action_map, action, err)) + + // check conflict action running + CHECK_ERR(ConflictActionRunning(env_data->action_map, action, err)) + + // check dependent action running + CHECK_ERR(DependentActionRunning(env_data->action_map, action, err)) + + // set action running flag + env_data->action_map.insert(make_pair(action, true)); + // get file name switch (action) { case START_CPU_PROFILING: - cpuprofile_filepath = CreateFilepath(prefix, ext); - result["filepath"] = cpuprofile_filepath; + env_data->cpuprofile_filepath = CreateFilepath(prefix, ext); + result["filepath"] = env_data->cpuprofile_filepath; break; case STOP_CPU_PROFILING: - result["filepath"] = cpuprofile_filepath; + result["filepath"] = env_data->cpuprofile_filepath; break; case HEAPDUMP: - heapsnapshot_filepath = CreateFilepath(prefix, ext); - result["filepath"] = heapsnapshot_filepath; + env_data->heapsnapshot_filepath = CreateFilepath(prefix, ext); + result["filepath"] = env_data->heapsnapshot_filepath; break; case START_SAMPLING_HEAP_PROFILING: - sampling_heapprofile_filepath = CreateFilepath(prefix, ext); - result["filepath"] = sampling_heapprofile_filepath; + env_data->sampling_heapprofile_filepath = CreateFilepath(prefix, ext); + result["filepath"] = env_data->sampling_heapprofile_filepath; break; case STOP_SAMPLING_HEAP_PROFILING: - result["filepath"] = sampling_heapprofile_filepath; + result["filepath"] = env_data->sampling_heapprofile_filepath; break; case START_GC_PROFILING: - gcprofile_filepath = CreateFilepath(prefix, ext); - result["filepath"] = gcprofile_filepath; + env_data->gcprofile_filepath = CreateFilepath(prefix, ext); + result["filepath"] = env_data->gcprofile_filepath; break; case STOP_GC_PROFILING: - result["filepath"] = gcprofile_filepath; + result["filepath"] = env_data->gcprofile_filepath; break; case NODE_REPORT: - node_report_filepath = CreateFilepath(prefix, ext); - result["filepath"] = node_report_filepath; + env_data->node_report_filepath = CreateFilepath(prefix, ext); + result["filepath"] = env_data->node_report_filepath; break; case COREDUMP: #ifdef __linux__ - coredump_filepath = CreateFilepath(prefix, ext); - result["filepath"] = coredump_filepath; + env_data->coredump_filepath = CreateFilepath(prefix, ext); + result["filepath"] = env_data->coredump_filepath; #else err = XpfError::Failure("generate_coredump only support linux now."); - action_map.erase(COREDUMP); + env_data->action_map.erase(COREDUMP); #endif break; default: @@ -411,8 +414,8 @@ static json DoDumpAction(json command, string prefix, string ext, T* data, if (err.Success()) { data->run_once = false; data->profiling_time = profiling_time; - uv_thread_create(&uv_profiling_callback_thread, ProfilingWatchDog, - (void*)data); + uv_thread_create(env_data->uv_profiling_callback_thread(), + ProfilingWatchDog, (void*)data); } else { err = XpfError::Succeed(); } diff --git a/src/environment_data.h b/src/environment_data.h index ac32d96..b7fd925 100644 --- a/src/environment_data.h +++ b/src/environment_data.h @@ -5,6 +5,7 @@ #include #include "commands/cpuprofiler/cpu_profiler.h" +#include "commands/dump.h" #include "commands/gcprofiler/gc_profiler.h" #include "library/common.h" #include "logbypass/gc.h" @@ -65,6 +66,18 @@ class EnvironmentData { std::unique_ptr gc_profiler; std::unique_ptr cpu_profiler; + // dump action + inline uv_thread_t* uv_profiling_callback_thread() { + return &uv_profiling_callback_thread_; + }; + ActionMap action_map; + std::string cpuprofile_filepath = ""; + std::string sampling_heapprofile_filepath = ""; + std::string heapsnapshot_filepath = ""; + std::string gcprofile_filepath = ""; + std::string node_report_filepath = ""; + std::string coredump_filepath = ""; + private: static void AtExit(void* arg); template @@ -80,6 +93,7 @@ class EnvironmentData { v8::Isolate* isolate_; uv_loop_t* loop_; uv_async_t statistics_async_; + uv_thread_t uv_profiling_callback_thread_; bool is_main_thread_ = false; /* We don't have a native method to get the uint64_t thread id. From 0813fd30b5542c21c0574f1d799effb369d14907 Mon Sep 17 00:00:00 2001 From: hyj1991 Date: Wed, 12 Oct 2022 11:31:07 +0800 Subject: [PATCH 2/3] remove useless code --- src/commands/dump.cc | 45 ++++++++++++++------------------------------ 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/src/commands/dump.cc b/src/commands/dump.cc index 803db18..7881bdb 100644 --- a/src/commands/dump.cc +++ b/src/commands/dump.cc @@ -174,6 +174,7 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { CpuProfilerDumpData* tmp = GetProfilingData( isolate, data, notify_type, unique_key); CpuProfiler::StartProfiling(isolate, tmp->title); + tmp->action = STOP_CPU_PROFILING; break; } case STOP_CPU_PROFILING: { @@ -195,9 +196,11 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { break; } case START_SAMPLING_HEAP_PROFILING: { - GetProfilingData(isolate, data, notify_type, - unique_key); + SamplingHeapProfilerDumpData* tmp = + GetProfilingData( + isolate, data, notify_type, unique_key); SamplingHeapProfiler::StartSamplingHeapProfiling(isolate); + tmp->action = STOP_SAMPLING_HEAP_PROFILING; break; } case STOP_SAMPLING_HEAP_PROFILING: { @@ -211,9 +214,10 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { break; } case START_GC_PROFILING: { - GetProfilingData(isolate, data, notify_type, - unique_key); + GcProfilerDumpData* tmp = GetProfilingData( + isolate, data, notify_type, unique_key); GcProfiler::StartGCProfiling(isolate, env_data->gcprofile_filepath); + tmp->action = STOP_GC_PROFILING; break; } case STOP_GC_PROFILING: { @@ -272,11 +276,13 @@ static void NotifyJsThread(EnvironmentData* env_data, void* data) { }); } -template -void StopProfiling(T* dump_data) { +static void ProfilingWatchDog(void* data) { + BaseDumpData* dump_data = static_cast(data); + + // sleep for profiling time WaitForProfile(dump_data->profiling_time); - dump_data->action = stop_action; + // get environment ThreadId thread_id = dump_data->thread_id; EnvironmentRegistry* registry = ProcessData::Get()->environment_registry(); EnvironmentRegistry::NoExitScope scope(registry); @@ -284,31 +290,8 @@ void StopProfiling(T* dump_data) { if (env_data == nullptr) { return; } - NotifyJsThread(env_data, dump_data); -} - -static void ProfilingWatchDog(void* data) { - BaseDumpData* dump_data = static_cast(data); - string traceid = dump_data->traceid; - DumpAction action = dump_data->action; - switch (action) { - case START_CPU_PROFILING: - StopProfiling( - static_cast(dump_data)); - break; - case START_SAMPLING_HEAP_PROFILING: - StopProfiling( - static_cast(dump_data)); - break; - case START_GC_PROFILING: - StopProfiling( - static_cast(dump_data)); - break; - default: - Error(module_type, "watch dog not support dump action: %s", action); - break; - } + NotifyJsThread(env_data, dump_data); } static string CreateFilepath(string prefix, string ext) { From cdcc5a8fc8a94823b9729c753487c880e7dad539 Mon Sep 17 00:00:00 2001 From: hyj1991 Date: Wed, 12 Oct 2022 16:24:52 +0800 Subject: [PATCH 3/3] fix --- src/commands/dump.cc | 40 ++++++++++++++++++++-------------------- src/environment_data.h | 4 +++- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/commands/dump.cc b/src/commands/dump.cc index 7881bdb..5c17832 100644 --- a/src/commands/dump.cc +++ b/src/commands/dump.cc @@ -77,13 +77,13 @@ string Action2String(DumpAction action) { return name; } -void ActionRunning(ActionMap action_map, DumpAction action, XpfError& err) { - if (action_map.find(action) != action_map.end()) { +void ActionRunning(ActionMap* action_map, DumpAction action, XpfError& err) { + if (action_map->find(action) != action_map->end()) { err = XpfError::Failure("%s is running.", Action2String(action).c_str()); } } -void ConflictActionRunning(ActionMap action_map, DumpAction action, +void ConflictActionRunning(ActionMap* action_map, DumpAction action, XpfError& err) { if (conflict_map.find(action) != conflict_map.end()) { for (DumpAction confilct : conflict_map.at(action)) { @@ -98,7 +98,7 @@ void ConflictActionRunning(ActionMap action_map, DumpAction action, } } -void DependentActionRunning(ActionMap action_map, DumpAction action, +void DependentActionRunning(ActionMap* action_map, DumpAction action, XpfError& err) { if (dependent_map.find(action) != dependent_map.end()) { DumpAction dependent_action = dependent_map.at(action); @@ -163,10 +163,10 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { notify_type.c_str(), unique_key.c_str()); // check conflict action running - CHECK_ERR(ConflictActionRunning(env_data->action_map, action, err)) + CHECK_ERR(ConflictActionRunning(env_data->action_map(), action, err)) // check dependent action running - CHECK_ERR(DependentActionRunning(env_data->action_map, action, err)) + CHECK_ERR(DependentActionRunning(env_data->action_map(), action, err)) // start run action switch (action) { @@ -184,15 +184,15 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { env_data->cpuprofile_filepath); AfterDumpFile(isolate, env_data->cpuprofile_filepath, notify_type, unique_key); - env_data->action_map.erase(START_CPU_PROFILING); - env_data->action_map.erase(STOP_CPU_PROFILING); + env_data->action_map()->erase(START_CPU_PROFILING); + env_data->action_map()->erase(STOP_CPU_PROFILING); break; } case HEAPDUMP: { HeapProfiler::TakeSnapshot(isolate, env_data->heapsnapshot_filepath); AfterDumpFile(isolate, env_data->heapsnapshot_filepath, notify_type, unique_key); - env_data->action_map.erase(HEAPDUMP); + env_data->action_map()->erase(HEAPDUMP); break; } case START_SAMPLING_HEAP_PROFILING: { @@ -209,8 +209,8 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { isolate, env_data->sampling_heapprofile_filepath); AfterDumpFile(isolate, env_data->sampling_heapprofile_filepath, notify_type, unique_key); - env_data->action_map.erase(START_SAMPLING_HEAP_PROFILING); - env_data->action_map.erase(STOP_SAMPLING_HEAP_PROFILING); + env_data->action_map()->erase(START_SAMPLING_HEAP_PROFILING); + env_data->action_map()->erase(STOP_SAMPLING_HEAP_PROFILING); break; } case START_GC_PROFILING: { @@ -225,22 +225,22 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) { GcProfiler::StopGCProfiling(isolate); AfterDumpFile(isolate, env_data->gcprofile_filepath, notify_type, unique_key); - env_data->action_map.erase(START_GC_PROFILING); - env_data->action_map.erase(STOP_GC_PROFILING); + env_data->action_map()->erase(START_GC_PROFILING); + env_data->action_map()->erase(STOP_GC_PROFILING); break; } case NODE_REPORT: { NodeReport::GetNodeReport(isolate, env_data->node_report_filepath); AfterDumpFile(isolate, env_data->node_report_filepath, notify_type, unique_key); - env_data->action_map.erase(NODE_REPORT); + env_data->action_map()->erase(NODE_REPORT); break; } case COREDUMP: { Coredumper::WriteCoredump(env_data->coredump_filepath); AfterDumpFile(isolate, env_data->coredump_filepath, notify_type, unique_key); - env_data->action_map.erase(COREDUMP); + env_data->action_map()->erase(COREDUMP); break; } default: @@ -324,16 +324,16 @@ static json DoDumpAction(json command, string prefix, string ext, T* data, } // check action running - CHECK_ERR(ActionRunning(env_data->action_map, action, err)) + CHECK_ERR(ActionRunning(env_data->action_map(), action, err)) // check conflict action running - CHECK_ERR(ConflictActionRunning(env_data->action_map, action, err)) + CHECK_ERR(ConflictActionRunning(env_data->action_map(), action, err)) // check dependent action running - CHECK_ERR(DependentActionRunning(env_data->action_map, action, err)) + CHECK_ERR(DependentActionRunning(env_data->action_map(), action, err)) // set action running flag - env_data->action_map.insert(make_pair(action, true)); + env_data->action_map()->insert(make_pair(action, true)); // get file name switch (action) { @@ -372,7 +372,7 @@ static json DoDumpAction(json command, string prefix, string ext, T* data, result["filepath"] = env_data->coredump_filepath; #else err = XpfError::Failure("generate_coredump only support linux now."); - env_data->action_map.erase(COREDUMP); + env_data->action_map()->erase(COREDUMP); #endif break; default: diff --git a/src/environment_data.h b/src/environment_data.h index b7fd925..17b9cab 100644 --- a/src/environment_data.h +++ b/src/environment_data.h @@ -70,7 +70,7 @@ class EnvironmentData { inline uv_thread_t* uv_profiling_callback_thread() { return &uv_profiling_callback_thread_; }; - ActionMap action_map; + inline ActionMap* action_map() { return &action_map_; } std::string cpuprofile_filepath = ""; std::string sampling_heapprofile_filepath = ""; std::string heapsnapshot_filepath = ""; @@ -115,6 +115,8 @@ class EnvironmentData { uint32_t closed_handle_count_ = 0; static const uint32_t kHandleCount = 2; + + ActionMap action_map_; }; } // namespace xprofiler