diff --git a/src/commands/dump.cc b/src/commands/dump.cc index 1cf4eb7..b338214 100644 --- a/src/commands/dump.cc +++ b/src/commands/dump.cc @@ -221,11 +221,11 @@ void HandleAction(void *data, string notify_type) { break; } case START_GC_PROFILING: { - GcProfiler::StartGCProfiling(gcprofile_filepath); + GcProfiler::StartGCProfiling(node_isolate, gcprofile_filepath); break; } case STOP_GC_PROFILING: { - GcProfiler::StopGCProfiling(); + GcProfiler::StopGCProfiling(node_isolate); AfterDumpFile(gcprofile_filepath, notify_type, unique_key); action_map.erase(START_GC_PROFILING); action_map.erase(STOP_GC_PROFILING); diff --git a/src/commands/gcprofiler/gc_profiler.cc b/src/commands/gcprofiler/gc_profiler.cc index 136ced2..6bbbd8b 100644 --- a/src/commands/gcprofiler/gc_profiler.cc +++ b/src/commands/gcprofiler/gc_profiler.cc @@ -1,8 +1,9 @@ #include "gc_profiler.h" -#include "../../library/writer.h" -#include "../../logbypass/gc.h" -#include "../../logger.h" +#include "environment_data.h" +#include "library/writer.h" +#include "logbypass/gc.h" +#include "logger.h" #include "nan.h" namespace xprofiler { @@ -15,90 +16,102 @@ using std::ofstream; using v8::GCType; using v8::HeapSpaceStatistics; -static string filename = ""; -static ofstream outfile; -static JSONWriter *writer = nullptr; -uint64_t init = 0; - -#define SPACE_DATA(tag) \ - if (type == GCType::kGCTypeScavenge) { \ - writer->json_keyvalue("type", "scavenge"); \ - } else if (type == GCType::kGCTypeMarkSweepCompact) { \ - writer->json_keyvalue("type", "marksweep"); \ - } else if (type == GCType::kGCTypeIncrementalMarking) { \ - writer->json_keyvalue("type", "marking"); \ - } else if (type == GCType::kGCTypeProcessWeakCallbacks) { \ - writer->json_keyvalue("type", "weakcallbacks"); \ - } else { \ - writer->json_keyvalue("type", static_cast(type)); \ - } \ - HeapSpaceStatistics s; \ - size_t number_of_heap_spaces = isolate->NumberOfHeapSpaces(); \ - writer->json_arraystart(tag); \ - for (size_t i = 0; i < number_of_heap_spaces; i++) { \ - writer->json_start(); \ - isolate->GetHeapSpaceStatistics(&s, i); \ - writer->json_keyvalue("name", s.space_name()); \ - writer->json_keyvalue("space_size", s.space_size()); \ - writer->json_keyvalue("space_used_size", s.space_used_size()); \ - writer->json_keyvalue("space_available_size", s.space_available_size()); \ - writer->json_keyvalue("physical_space_size", s.physical_space_size()); \ - writer->json_end(); \ - } \ +inline void write_space_data(v8::Isolate* isolate, GCType type, + JSONWriter* writer, const char* tag) { + if (type == GCType::kGCTypeScavenge) { + writer->json_keyvalue("type", "scavenge"); + } else if (type == GCType::kGCTypeMarkSweepCompact) { + writer->json_keyvalue("type", "marksweep"); + } else if (type == GCType::kGCTypeIncrementalMarking) { + writer->json_keyvalue("type", "marking"); + } else if (type == GCType::kGCTypeProcessWeakCallbacks) { + writer->json_keyvalue("type", "weakcallbacks"); + } else { + writer->json_keyvalue("type", static_cast(type)); + } + HeapSpaceStatistics s; + size_t number_of_heap_spaces = isolate->NumberOfHeapSpaces(); + writer->json_arraystart(tag); + for (size_t i = 0; i < number_of_heap_spaces; i++) { + writer->json_start(); + isolate->GetHeapSpaceStatistics(&s, i); + writer->json_keyvalue("name", s.space_name()); + writer->json_keyvalue("space_size", s.space_size()); + writer->json_keyvalue("space_used_size", s.space_used_size()); + writer->json_keyvalue("space_available_size", s.space_available_size()); + writer->json_keyvalue("physical_space_size", s.physical_space_size()); + writer->json_end(); + } writer->json_arrayend(); - -GcProfiler::GcProfiler() {} -GcProfiler::~GcProfiler() {} +} NAN_GC_CALLBACK(GCTracerPrologueCallback) { + EnvironmentData* env_data = EnvironmentData::GetCurrent(isolate); + if (env_data->gc_profiler == nullptr) { + return; + } + JSONWriter* writer = env_data->gc_profiler->writer(); writer->json_start(); writer->json_keyvalue("totalSpentfromStart", TotalGcDuration()); writer->json_keyvalue("totalTimesfromStart", TotalGcTimes()); writer->json_keyvalue("timeFromStart", GetUptime()); - writer->json_keyvalue("start", static_cast((uv_hrtime() - init) / 10e5)); - SPACE_DATA("before"); + writer->json_keyvalue("start", + (uv_hrtime() - env_data->gc_profiler->init()) / 10e5); + write_space_data(isolate, type, writer, "before"); } NAN_GC_CALLBACK(GCTracerEpilogueCallback) { - writer->json_keyvalue("end", static_cast((uv_hrtime() - init) / 10e5)); - SPACE_DATA("after"); + EnvironmentData* env_data = EnvironmentData::GetCurrent(isolate); + if (env_data->gc_profiler == nullptr) { + return; + } + JSONWriter* writer = env_data->gc_profiler->writer(); + writer->json_keyvalue("end", + (uv_hrtime() - env_data->gc_profiler->init()) / 10e5); + write_space_data(isolate, type, writer, "after"); writer->json_end(); } -void GcProfiler::StartGCProfiling(string filename_) { - outfile.open(filename_, ios::out | ios::binary); - if (!outfile.is_open()) { - Error("gc_profiler", "open file %s failed.", filename_.c_str()); - outfile.close(); +void GcProfiler::StartGCProfiling(v8::Isolate* isolate, std::string filename) { + EnvironmentData* env_data = EnvironmentData::GetCurrent(isolate); + std::unique_ptr gc_profiler = + std::unique_ptr(new GcProfiler(isolate, filename)); + if (!gc_profiler->is_open()) { + Error("gc_profiler", "open file %s failed.", filename.c_str()); return; } + env_data->gc_profiler = std::move(gc_profiler); + AddGCPrologueCallback(GCTracerPrologueCallback); AddGCEpilogueCallback(GCTracerEpilogueCallback); - filename = filename_; - writer = new JSONWriter(outfile); - init = uv_hrtime(); + + JSONWriter* writer = env_data->gc_profiler->writer(); writer->json_start(); - writer->json_keyvalue("startTime", - static_cast(uv_hrtime() / 10e8)); + writer->json_keyvalue("startTime", uv_hrtime() / 10e8); writer->json_arraystart("gc"); } -void GcProfiler::StopGCProfiling() { +void GcProfiler::StopGCProfiling(v8::Isolate* isolate) { RemoveGCPrologueCallback(GCTracerPrologueCallback); RemoveGCEpilogueCallback(GCTracerEpilogueCallback); - if (writer != nullptr) { - writer->json_arrayend(); - writer->json_keyvalue("stopTime", - static_cast(uv_hrtime() / 10e8)); - writer->json_end(); - delete writer; - } - if (filename != "") { - filename = ""; - } - if (outfile.is_open()) { - outfile.close(); + EnvironmentData* env_data = EnvironmentData::GetCurrent(isolate); + if (env_data->gc_profiler == nullptr) { + return; } - init = 0; + JSONWriter* writer = env_data->gc_profiler->writer(); + writer->json_arrayend(); + writer->json_keyvalue("stopTime", uv_hrtime() / 10e8); + writer->json_end(); + + env_data->gc_profiler.reset(); } -} // namespace xprofiler \ No newline at end of file + +GcProfiler::GcProfiler(v8::Isolate* isolate, std::string filename) + : filename_(filename), + outfile_(filename, ios::out | ios::binary), + writer_(outfile_), + init_(uv_hrtime()) {} + +GcProfiler::~GcProfiler() {} + +} // namespace xprofiler diff --git a/src/commands/gcprofiler/gc_profiler.h b/src/commands/gcprofiler/gc_profiler.h index 0160426..5cd058e 100644 --- a/src/commands/gcprofiler/gc_profiler.h +++ b/src/commands/gcprofiler/gc_profiler.h @@ -1,18 +1,33 @@ -#ifndef _SRC_COMMANDS_GCPROFILER_GC_PROFILER_H -#define _SRC_COMMANDS_GCPROFILER_GC_PROFILER_H +#ifndef XPROFILER_SRC_COMMANDS_GCPROFILER_GC_PROFILER_H +#define XPROFILER_SRC_COMMANDS_GCPROFILER_GC_PROFILER_H #include +#include "library/writer.h" +#include "nan.h" + namespace xprofiler { -using std::string; class GcProfiler { public: - GcProfiler(); - virtual ~GcProfiler(); - static void StartGCProfiling(string filename); - static void StopGCProfiling(); + static void StartGCProfiling(v8::Isolate* isolate, std::string filename); + static void StopGCProfiling(v8::Isolate* isolate); + + ~GcProfiler(); + + bool is_open() { return outfile_.is_open(); } + JSONWriter* writer() { return &writer_; } + uint64_t init() { return init_; } + + private: + GcProfiler(v8::Isolate* isolate, std::string filename); + + std::string filename_ = ""; + std::ofstream outfile_; + JSONWriter writer_; + uint64_t init_ = 0; }; } // namespace xprofiler -#endif + +#endif /* XPROFILER_SRC_COMMANDS_GCPROFILER_GC_PROFILER_H */ diff --git a/src/environment_data.h b/src/environment_data.h index adc2905..a5c64df 100644 --- a/src/environment_data.h +++ b/src/environment_data.h @@ -1,6 +1,7 @@ #ifndef XPROFILER_SRC_ENVIRONMENT_DATA_H #define XPROFILER_SRC_ENVIRONMENT_DATA_H +#include "commands/gcprofiler/gc_profiler.h" #include "logbypass/gc.h" #include "logbypass/heap.h" #include "logbypass/http.h" @@ -30,6 +31,8 @@ class EnvironmentData { return &uv_handle_statistics_; } + std::unique_ptr gc_profiler; + private: static void AtExit(void* arg); static void CollectStatistics(uv_async_t* handle);