summaryrefslogtreecommitdiff
path: root/src/node_counters.cc
diff options
context:
space:
mode:
authorScott Blomquist <sblom@microsoft.com>2012-11-21 00:27:22 +0100
committerBert Belder <bertbelder@gmail.com>2012-11-21 01:21:53 +0100
commitf657ce685dddc1bf2d5b42f56d728df9176cceb9 (patch)
treeff03ca0dcd8c3260257c9b8c9e842829e7372db8 /src/node_counters.cc
parentbc9388342f59ed5c69d69c7095e5a17fcbd80ba8 (diff)
downloadnode-f657ce685dddc1bf2d5b42f56d728df9176cceb9.tar.gz
windows: add tracing with performance counters
Patch by Henry Rawas and Scott Blomquist.
Diffstat (limited to 'src/node_counters.cc')
-rw-r--r--src/node_counters.cc149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/node_counters.cc b/src/node_counters.cc
new file mode 100644
index 000000000..3c8d49c00
--- /dev/null
+++ b/src/node_counters.cc
@@ -0,0 +1,149 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include "node_counters.h"
+
+#include "uv.h"
+
+#include <string.h>
+
+
+namespace node {
+
+using namespace v8;
+
+
+static uint64_t counter_gc_start_time;
+static uint64_t counter_gc_end_time;
+
+#define SLURP_OBJECT(obj, member, valp) \
+ if (!(obj)->IsObject()) { \
+ return (ThrowException(Exception::Error(String::New("expected " \
+ "object for " #obj " to contain object member " #member)))); \
+ } \
+ *valp = Local<Object>::Cast(obj->Get(String::New(#member)));
+
+
+Handle<Value> COUNTER_NET_SERVER_CONNECTION(const Arguments& args) {
+ NODE_COUNT_SERVER_CONN_OPEN();
+ return Undefined();
+}
+
+
+Handle<Value> COUNTER_NET_SERVER_CONNECTION_CLOSE(const Arguments& args) {
+ NODE_COUNT_SERVER_CONN_CLOSE();
+ return Undefined();
+}
+
+
+Handle<Value> COUNTER_HTTP_SERVER_REQUEST(const Arguments& args) {
+ NODE_COUNT_HTTP_SERVER_REQUEST();
+ return Undefined();
+}
+
+
+Handle<Value> COUNTER_HTTP_SERVER_RESPONSE(const Arguments& args) {
+ NODE_COUNT_HTTP_SERVER_RESPONSE();
+ return Undefined();
+}
+
+
+Handle<Value> COUNTER_HTTP_CLIENT_REQUEST(const Arguments& args) {
+ NODE_COUNT_HTTP_CLIENT_REQUEST();
+ return Undefined();
+}
+
+
+Handle<Value> COUNTER_HTTP_CLIENT_RESPONSE(const Arguments& args) {
+ NODE_COUNT_HTTP_CLIENT_RESPONSE();
+ return Undefined();
+}
+
+
+static void counter_gc_start(GCType type, GCCallbackFlags flags) {
+ counter_gc_start_time = NODE_COUNT_GET_GC_RAWTIME();
+
+ return;
+}
+
+
+static void counter_gc_done(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<unsigned int>((gcperiod * 100) / totalperiod);
+
+ NODE_COUNT_GC_PERCENTTIME(percent);
+ counter_gc_end_time = endgc;
+ }
+ }
+
+ return;
+}
+
+
+#define NODE_PROBE(name) #name, name
+
+void InitPerfCounters(Handle<Object> target) {
+ HandleScope scope;
+
+ static struct {
+ const char* name;
+ Handle<Value> (*func)(const Arguments&);
+ Persistent<FunctionTemplate> templ;
+ } tab[] = {
+ { 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) }
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(tab); i++) {
+ tab[i].templ = Persistent<FunctionTemplate>::New(
+ FunctionTemplate::New(tab[i].func));
+ target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction());
+ }
+
+ // 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;
+
+ v8::V8::AddGCPrologueCallback(counter_gc_start);
+ v8::V8::AddGCEpilogueCallback(counter_gc_done);
+}
+
+
+void TermPerfCounters(Handle<Object> target) {
+ // Only Windows performance counters supported
+ // To enable other OS, use conditional compilation here
+ TermPerfCountersWin32();
+}
+
+}