#include "node_counters.h" #include "uv.h" #include "env.h" #include "env-inl.h" #include namespace node { using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::GCCallbackFlags; using v8::GCEpilogueCallback; using v8::GCPrologueCallback; using v8::GCType; using v8::Handle; using v8::HandleScope; using v8::Isolate; using v8::Local; using v8::Object; using v8::String; using v8::Value; static uint64_t counter_gc_start_time; static uint64_t counter_gc_end_time; void COUNTER_NET_SERVER_CONNECTION(const FunctionCallbackInfo&) { NODE_COUNT_SERVER_CONN_OPEN(); } void COUNTER_NET_SERVER_CONNECTION_CLOSE(const FunctionCallbackInfo&) { NODE_COUNT_SERVER_CONN_CLOSE(); } void COUNTER_HTTP_SERVER_REQUEST(const FunctionCallbackInfo&) { NODE_COUNT_HTTP_SERVER_REQUEST(); } void COUNTER_HTTP_SERVER_RESPONSE(const FunctionCallbackInfo&) { NODE_COUNT_HTTP_SERVER_RESPONSE(); } void COUNTER_HTTP_CLIENT_REQUEST(const FunctionCallbackInfo&) { NODE_COUNT_HTTP_CLIENT_REQUEST(); } void COUNTER_HTTP_CLIENT_RESPONSE(const FunctionCallbackInfo&) { NODE_COUNT_HTTP_CLIENT_RESPONSE(); } static void counter_gc_start(Isolate* isolate, GCType type, GCCallbackFlags flags) { counter_gc_start_time = NODE_COUNT_GET_GC_RAWTIME(); } static void counter_gc_done(Isolate* isolate, GCType type, GCCallbackFlags flags) { uint64_t endgc = NODE_COUNT_GET_GC_RAWTIME(); if (endgc != 0) { uint64_t totalperiod = endgc - counter_gc_end_time; uint64_t gcperiod = endgc - counter_gc_start_time; if (totalperiod > 0) { unsigned int percent = static_cast( (gcperiod * 100) / totalperiod); NODE_COUNT_GC_PERCENTTIME(percent); counter_gc_end_time = endgc; } } } void InitPerfCounters(Environment* env, Handle target) { HandleScope scope(env->isolate()); static struct { const char* name; void (*func)(const FunctionCallbackInfo&); } tab[] = { #define NODE_PROBE(name) #name, name { NODE_PROBE(COUNTER_NET_SERVER_CONNECTION) }, { NODE_PROBE(COUNTER_NET_SERVER_CONNECTION_CLOSE) }, { NODE_PROBE(COUNTER_HTTP_SERVER_REQUEST) }, { NODE_PROBE(COUNTER_HTTP_SERVER_RESPONSE) }, { NODE_PROBE(COUNTER_HTTP_CLIENT_REQUEST) }, { NODE_PROBE(COUNTER_HTTP_CLIENT_RESPONSE) } #undef NODE_PROBE }; for (int i = 0; i < ARRAY_SIZE(tab); i++) { Local key = OneByteString(env->isolate(), tab[i].name); Local val = env->NewFunctionTemplate(tab[i].func)->GetFunction(); target->Set(key, val); } // Only Windows performance counters supported // To enable other OS, use conditional compilation here InitPerfCountersWin32(); // init times for GC percent calculation and hook callbacks counter_gc_start_time = NODE_COUNT_GET_GC_RAWTIME(); counter_gc_end_time = counter_gc_start_time; env->isolate()->AddGCPrologueCallback(counter_gc_start); env->isolate()->AddGCEpilogueCallback(counter_gc_done); } void TermPerfCounters(Handle target) { // Only Windows performance counters supported // To enable other OS, use conditional compilation here TermPerfCountersWin32(); } } // namespace node