Merge remote-tracking branch 'ry/v0.10'
[platform/upstream/nodejs.git] / src / node_counters.cc
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #include "node_counters.h"
23
24 #include "uv.h"
25
26 #include <string.h>
27
28
29 namespace node {
30
31 using namespace v8;
32
33
34 static uint64_t counter_gc_start_time;
35 static uint64_t counter_gc_end_time;
36
37 #define SLURP_OBJECT(obj, member, valp) \
38   if (!(obj)->IsObject()) { \
39     return (ThrowException(Exception::Error(String::New("expected " \
40       "object for " #obj " to contain object member " #member)))); \
41   } \
42   *valp = Local<Object>::Cast(obj->Get(String::New(#member)));
43
44
45 Handle<Value> COUNTER_NET_SERVER_CONNECTION(const Arguments& args) {
46   NODE_COUNT_SERVER_CONN_OPEN();
47   return Undefined(node_isolate);
48 }
49
50
51 Handle<Value> COUNTER_NET_SERVER_CONNECTION_CLOSE(const Arguments& args) {
52   NODE_COUNT_SERVER_CONN_CLOSE();
53   return Undefined(node_isolate);
54 }
55
56
57 Handle<Value> COUNTER_HTTP_SERVER_REQUEST(const Arguments& args) {
58   NODE_COUNT_HTTP_SERVER_REQUEST();
59   return Undefined(node_isolate);
60 }
61
62
63 Handle<Value> COUNTER_HTTP_SERVER_RESPONSE(const Arguments& args) {
64   NODE_COUNT_HTTP_SERVER_RESPONSE();
65   return Undefined(node_isolate);
66 }
67
68
69 Handle<Value> COUNTER_HTTP_CLIENT_REQUEST(const Arguments& args) {
70   NODE_COUNT_HTTP_CLIENT_REQUEST();
71   return Undefined(node_isolate);
72 }
73
74
75 Handle<Value> COUNTER_HTTP_CLIENT_RESPONSE(const Arguments& args) {
76   NODE_COUNT_HTTP_CLIENT_RESPONSE();
77   return Undefined(node_isolate);
78 }
79
80
81 static void counter_gc_start(GCType type, GCCallbackFlags flags) {
82   counter_gc_start_time = NODE_COUNT_GET_GC_RAWTIME();
83
84   return;
85 }
86
87
88 static void counter_gc_done(GCType type, GCCallbackFlags flags) {
89   uint64_t endgc = NODE_COUNT_GET_GC_RAWTIME();
90   if (endgc != 0) {
91     uint64_t totalperiod = endgc - counter_gc_end_time;
92     uint64_t gcperiod = endgc - counter_gc_start_time;
93
94     if (totalperiod > 0) {
95       unsigned int percent = static_cast<unsigned int>((gcperiod * 100) / totalperiod);
96
97       NODE_COUNT_GC_PERCENTTIME(percent);
98       counter_gc_end_time = endgc;
99     }
100   }
101
102   return;
103 }
104
105
106 #define NODE_PROBE(name) #name, name
107
108 void InitPerfCounters(Handle<Object> target) {
109   HandleScope scope(node_isolate);
110
111   static struct {
112     const char* name;
113     Handle<Value> (*func)(const Arguments&);
114     Persistent<FunctionTemplate> templ;
115   } tab[] = {
116     { NODE_PROBE(COUNTER_NET_SERVER_CONNECTION) },
117     { NODE_PROBE(COUNTER_NET_SERVER_CONNECTION_CLOSE) },
118     { NODE_PROBE(COUNTER_HTTP_SERVER_REQUEST) },
119     { NODE_PROBE(COUNTER_HTTP_SERVER_RESPONSE) },
120     { NODE_PROBE(COUNTER_HTTP_CLIENT_REQUEST) },
121     { NODE_PROBE(COUNTER_HTTP_CLIENT_RESPONSE) }
122   };
123
124   for (int i = 0; i < ARRAY_SIZE(tab); i++) {
125     tab[i].templ = Persistent<FunctionTemplate>::New(node_isolate,
126         FunctionTemplate::New(tab[i].func));
127     target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction());
128   }
129
130   // Only Windows performance counters supported
131   // To enable other OS, use conditional compilation here
132   InitPerfCountersWin32();
133
134   // init times for GC percent calculation and hook callbacks
135   counter_gc_start_time = NODE_COUNT_GET_GC_RAWTIME();
136   counter_gc_end_time = counter_gc_start_time;
137
138   v8::V8::AddGCPrologueCallback(counter_gc_start);
139   v8::V8::AddGCEpilogueCallback(counter_gc_done);
140 }
141
142
143 void TermPerfCounters(Handle<Object> target) {
144   // Only Windows performance counters supported
145   // To enable other OS, use conditional compilation here
146   TermPerfCountersWin32();
147 }
148
149 }