#include #include "v8.h" #include "v8-profiler.h" namespace allocation_sampler { const int MAX_DEPTH = 25; bool is_started = false; NAN_METHOD(CheckAllocationSampler) { #if V8_MAJOR_VERSION >= 5 if (info.GetIsolate()->GetHeapProfiler()) { info.GetReturnValue().Set(true); } else { info.GetReturnValue().Set(false); } #else info.GetReturnValue().Set(false); #endif } #if V8_MAJOR_VERSION >= 5 NAN_METHOD(StartAllocationSampler) { if(is_started) { return; } is_started = true; unsigned int sampling_interval = 1 << 19; info.GetIsolate()->GetHeapProfiler()->StartSamplingHeapProfiler(sampling_interval, MAX_DEPTH); } NAN_METHOD(StopAllocationSampler) { if(!is_started) { info.GetReturnValue().SetUndefined(); return; } is_started = false; info.GetIsolate()->GetHeapProfiler()->StopSamplingHeapProfiler(); } static v8::Local ConvertNode(const v8::AllocationProfile::Node* node, int depth) { v8::Local node_obj = Nan::New(); v8::Local children_arr = Nan::New(); unsigned int total_count = 0; size_t total_size = 0; for (auto allocation : node->allocations) { total_count += allocation.count; total_size += allocation.size * allocation.count; } if (depth + 1 < MAX_DEPTH) { int i = 0; for (auto child : node->children) { v8::Local child_obj = ConvertNode(child, depth + 1); Nan::Set(children_arr, i++, child_obj); } } Nan::Set(node_obj, Nan::New("file_name").ToLocalChecked(), node->script_name); Nan::Set(node_obj, Nan::New("line_num").ToLocalChecked(), Nan::New(node->line_number)); Nan::Set(node_obj, Nan::New("col_num").ToLocalChecked(), Nan::New(node->column_number)); Nan::Set(node_obj, Nan::New("func_name").ToLocalChecked(), node->name); Nan::Set(node_obj, Nan::New("count").ToLocalChecked(), Nan::New(total_count)); Nan::Set(node_obj, Nan::New("size").ToLocalChecked(), Nan::New(total_size)); Nan::Set(node_obj, Nan::New("children").ToLocalChecked(), children_arr); return node_obj; } NAN_METHOD(ReadAllocationProfile) { if(!is_started) { info.GetReturnValue().SetUndefined(); return; } v8::AllocationProfile *profile = info.GetIsolate()->GetHeapProfiler()->GetAllocationProfile(); if (profile) { v8::Local root_obj = ConvertNode(profile->GetRootNode(), 0); delete profile; profile = NULL; info.GetReturnValue().Set(root_obj); } else { info.GetReturnValue().SetUndefined(); } } #endif }