Skip to content

Commit 0e14562

Browse files
committed
First commit
0 parents  commit 0e14562

15 files changed

+611
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
build
2+
lib-cov
3+
node_modules
4+
.lock-wscript
5+
*.swp
6+
*.swo
7+
.DS_Store

binding.gyp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
'targets': [
3+
{
4+
'target_name': 'profiler',
5+
'sources': [
6+
'cpu_profiler.cc',
7+
'profile.cc',
8+
'profile_node.cc',
9+
'profiler.cc',
10+
],
11+
}
12+
]
13+
}

builderror.log

Whitespace-only changes.

cpu_profiler.cc

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#include "cpu_profiler.h"
2+
#include "profile.h"
3+
4+
namespace nodex {
5+
CpuProfiler::CpuProfiler () {}
6+
CpuProfiler::~CpuProfiler () {}
7+
8+
void CpuProfiler::Initialize (Handle<Object> target) {
9+
HandleScope scope;
10+
11+
NODE_SET_METHOD(target, "getProfilesCount", CpuProfiler::GetProfilesCount);
12+
NODE_SET_METHOD(target, "getProfile", CpuProfiler::GetProfile);
13+
NODE_SET_METHOD(target, "findProfile", CpuProfiler::FindProfile);
14+
NODE_SET_METHOD(target, "startProfiling", CpuProfiler::StartProfiling);
15+
NODE_SET_METHOD(target, "stopProfiling", CpuProfiler::StopProfiling);
16+
NODE_SET_METHOD(target, "deleteAllProfiles", CpuProfiler::DeleteAllProfiles);
17+
}
18+
19+
Handle<Value> CpuProfiler::GetProfilesCount (const Arguments& args) {
20+
HandleScope scope;
21+
return scope.Close(Integer::New(v8::CpuProfiler::GetProfilesCount()));
22+
}
23+
24+
Handle<Value> CpuProfiler::GetProfile (const Arguments& args) {
25+
HandleScope scope;
26+
if (args.Length() < 1) {
27+
return ThrowException(Exception::Error(String::New("No index specified")));
28+
} else if ( ! args[0]->IsInt32()) {
29+
return ThrowException(Exception::TypeError(String::New("Argument must be an integer")));
30+
}
31+
int32_t index = args[0]->Int32Value();
32+
const CpuProfile* profile = v8::CpuProfiler::GetProfile(index);
33+
return scope.Close(Profile::New(profile));
34+
}
35+
36+
Handle<Value> CpuProfiler::FindProfile (const Arguments& args) {
37+
HandleScope scope;
38+
if (args.Length() < 1) {
39+
return ThrowException(Exception::Error(String::New("No index specified")));
40+
} else if ( ! args[0]->IsInt32()) {
41+
return ThrowException(Exception::TypeError(String::New("Argument must be an integer")));
42+
}
43+
uint32_t uid = args[0]->Uint32Value();
44+
const CpuProfile* profile = v8::CpuProfiler::FindProfile(uid);
45+
return scope.Close(Profile::New(profile));
46+
}
47+
48+
Handle<Value> CpuProfiler::StartProfiling (const Arguments& args) {
49+
HandleScope scope;
50+
Local<String> title = args.Length() > 0 ? args[0]->ToString() : String::New("");
51+
v8::CpuProfiler::StartProfiling(title);
52+
return Undefined();
53+
}
54+
55+
Handle<Value> CpuProfiler::StopProfiling (const Arguments& args) {
56+
HandleScope scope;
57+
Local<String> title = args.Length() > 0 ? args[0]->ToString() : String::New("");
58+
const CpuProfile* profile = v8::CpuProfiler::StopProfiling(title);
59+
return scope.Close(Profile::New(profile));
60+
}
61+
62+
Handle<Value> CpuProfiler::DeleteAllProfiles (const Arguments& args) {
63+
v8::CpuProfiler::DeleteAllProfiles();
64+
return Undefined();
65+
}
66+
} //namespace nodex

cpu_profiler.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef NODE_CPU_PROFILER_
2+
#define NODE_CPU_PROFILER_
3+
4+
#include <v8-profiler.h>
5+
#include <node.h>
6+
7+
using namespace v8;
8+
using namespace node;
9+
10+
namespace nodex {
11+
class CpuProfiler {
12+
public:
13+
static void Initialize(Handle<Object> target);
14+
15+
CpuProfiler();
16+
virtual ~CpuProfiler();
17+
18+
protected:
19+
static Handle<Value> GetProfilesCount(const Arguments& args);
20+
static Handle<Value> GetProfile(const Arguments& args);
21+
static Handle<Value> FindProfile(const Arguments& args);
22+
static Handle<Value> StartProfiling(const Arguments& args);
23+
static Handle<Value> StopProfiling(const Arguments& args);
24+
static Handle<Value> DeleteAllProfiles(const Arguments& args);
25+
};
26+
} //namespace nodex
27+
28+
#endif // NODE_CPU_PROFILER_H

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
var base = process.env.STRONG_PROFILER_COV ? 'lib-cov' : 'lib';
2+
module.exports = require('./' + base + '/strong-profiler');

lib/strong-profiler.js

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Precompile the profiler module for 4 platforms: Windows, Solaris/SunOS, Linux, OSX
2+
// both 32 and 64 bit architectures
3+
//
4+
// lib_ver (example: 'v0.10.12') indicates the version (.12)
5+
// that the library was compiled under.
6+
//
7+
// we first try a locally compiled version; failing that we'll look for a
8+
// precompiled version
9+
10+
var version_map = {
11+
'v0.10.*': 'v0.10.12'
12+
};
13+
var platform = process.platform;
14+
var key, lib_ver;
15+
16+
if (platform === 'solaris') platform = 'sunos';
17+
18+
for (key in version_map) {
19+
if (RegExp(key).test(process.version)) {
20+
lib_ver = version_map[key];
21+
}
22+
}
23+
24+
// if lib_ver stays undefined require will fail and we'll catch it
25+
// same behaviour when there's a new version of node and we haven't
26+
// compiled for it yet
27+
var modpath = '../compiled/' + platform + '/' + process.arch + '/' + lib_ver
28+
+ '/profiler';
29+
var buildpath = '../build/Release/profiler';
30+
var binding
31+
32+
// try local build dir in case node-gyp was successful
33+
try { binding = require(buildpath); }
34+
catch (err) {
35+
// Try pre-built modules
36+
try { binding = require(modpath); }
37+
catch (err) {
38+
// stub out the API functions in case we were unable to load the native
39+
// module, which will prevent it from blowing up
40+
binding = {
41+
takeSnapshot: function(){},
42+
startProfiling: function(){},
43+
stopProfiling: function(){}
44+
}
45+
console.log('unable to load native module "profiler.node" from ' +
46+
buildpath + ' or ' + modpath);
47+
}
48+
}
49+
50+
function CpuProfile() {}
51+
52+
function inspectorObjectFor(node) {
53+
var i, count, child,
54+
result = {
55+
functionName: node.functionName,
56+
url: node.scriptName,
57+
lineNumber: node.lineNumber,
58+
totalTime: node.totalTime,
59+
selfTime: node.selfTime,
60+
numberOfCalls: 0,
61+
visible: true,
62+
callUID: node.callUid,
63+
children: []
64+
};
65+
for(i = 0, count = node.childrenCount; i < count; i++) {
66+
child = node.getChild(i);
67+
result.children.push(inspectorObjectFor(child));
68+
}
69+
return result;
70+
}
71+
72+
CpuProfile.prototype.getTopDownRoot = function() {
73+
return inspectorObjectFor(this.topRoot);
74+
};
75+
76+
CpuProfile.prototype.getBottomUpRoot = function() {
77+
return inspectorObjectFor(this.bottomRoot);
78+
};
79+
80+
var cpuCache = [];
81+
82+
exports.startProfiling = function(name) {
83+
if (!name || !name.length) {
84+
name = 'org.nodejs.profiles.cpu.user-initiated.' + (cpuCache.length + 1);
85+
}
86+
87+
binding.startProfiling(name);
88+
};
89+
90+
exports.stopProfiling = function(name) {
91+
name = name ? name : '';
92+
var profile = binding.stopProfiling(name);
93+
profile.__proto__ = CpuProfile.prototype;
94+
cpuCache.push(profile);
95+
return profile;
96+
};
97+
98+
exports.getProfile = function(index) {
99+
return cpuCache[index];
100+
};
101+
102+
exports.findProfile = function(uid) {
103+
return cpuCache.filter(function(s) {return s.uid === uid;})[0];
104+
};
105+
106+
exports.profileCount = function() {
107+
return cpuCache.length;
108+
};
109+
110+
exports.deleteAllProfiles = function() {
111+
cpuCache = [];
112+
binding.deleteAllProfiles();
113+
};
114+
115+
process.profiler = exports;

package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "strong-cpu-profiler",
3+
"version": "0.1.0",
4+
"description": "Node bindings for the v8 cpu profiler",
5+
"homepage": "http://github.com/strongloop/strong-cpu-profiler",
6+
"author": "Stephen Belanger <[email protected]>",
7+
"keywords": [ "profiler", "inspector", "cpu" ],
8+
"engines": { "node": ">=0.8" },
9+
"devDependencies": {
10+
"should": "*",
11+
"mocha": "*"
12+
},
13+
"scripts": {
14+
"install" : "(node-gyp rebuild 2> builderror.log) || (exit 0)",
15+
"test": "mocha -r should -G -R spec",
16+
"coverage": "rm -rf lib-cov && jscoverage lib lib-cov && STRONG_PROFILER_COV=1 mocha -r should -G -R html-cov > lib-cov/index.html && open lib-cov/index.html"
17+
}
18+
}

profile.cc

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include "profile.h"
2+
#include "profile_node.h"
3+
4+
using namespace v8;
5+
6+
namespace nodex {
7+
Persistent<ObjectTemplate> Profile::profile_template_;
8+
9+
void Profile::Initialize () {
10+
profile_template_ = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
11+
profile_template_->SetInternalFieldCount(1);
12+
profile_template_->SetAccessor(String::New("title"), Profile::GetTitle);
13+
profile_template_->SetAccessor(String::New("uid"), Profile::GetUid);
14+
profile_template_->SetAccessor(String::New("topRoot"), Profile::GetTopRoot);
15+
profile_template_->SetAccessor(String::New("bottomRoot"), Profile::GetBottomRoot);
16+
profile_template_->Set(String::New("delete"), FunctionTemplate::New(Profile::Delete));
17+
}
18+
19+
Handle<Value> Profile::GetUid (Local<String> property, const AccessorInfo& info) {
20+
HandleScope scope;
21+
Local<Object> self = info.Holder();
22+
void* ptr = self->GetPointerFromInternalField(0);
23+
uint32_t uid = static_cast<CpuProfile*>(ptr)->GetUid();
24+
return scope.Close(Integer::NewFromUnsigned(uid));
25+
}
26+
27+
28+
Handle<Value> Profile::GetTitle (Local<String> property, const AccessorInfo& info) {
29+
HandleScope scope;
30+
Local<Object> self = info.Holder();
31+
void* ptr = self->GetPointerFromInternalField(0);
32+
Handle<String> title = static_cast<CpuProfile*>(ptr)->GetTitle();
33+
return scope.Close(title);
34+
}
35+
36+
Handle<Value> Profile::GetTopRoot (Local<String> property, const AccessorInfo& info) {
37+
HandleScope scope;
38+
Local<Object> self = info.Holder();
39+
void* ptr = self->GetPointerFromInternalField(0);
40+
const CpuProfileNode* node = static_cast<CpuProfile*>(ptr)->GetTopDownRoot();
41+
return scope.Close(ProfileNode::New(node));
42+
}
43+
44+
45+
Handle<Value> Profile::GetBottomRoot (Local<String> property, const AccessorInfo& info) {
46+
HandleScope scope;
47+
Local<Object> self = info.Holder();
48+
void* ptr = self->GetPointerFromInternalField(0);
49+
const CpuProfileNode* node = static_cast<CpuProfile*>(ptr)->GetBottomUpRoot();
50+
return scope.Close(ProfileNode::New(node));
51+
}
52+
53+
Handle<Value> Profile::Delete (const Arguments& args) {
54+
HandleScope scope;
55+
Handle<Object> self = args.This();
56+
void* ptr = self->GetPointerFromInternalField(0);
57+
static_cast<CpuProfile*>(ptr)->Delete();
58+
return Undefined();
59+
}
60+
61+
Handle<Value> Profile::New (const CpuProfile* profile) {
62+
HandleScope scope;
63+
64+
if (profile_template_.IsEmpty()) {
65+
Profile::Initialize();
66+
}
67+
68+
if ( ! profile) {
69+
return Undefined();
70+
} else {
71+
Local<Object> obj = profile_template_->NewInstance();
72+
obj->SetPointerInInternalField(0, const_cast<CpuProfile*>(profile));
73+
return scope.Close(obj);
74+
}
75+
}
76+
}

profile.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef NODE_PROFILE_
2+
#define NODE_PROFILE_
3+
4+
#include <v8-profiler.h>
5+
6+
using namespace v8;
7+
8+
namespace nodex {
9+
10+
class Profile {
11+
public:
12+
static Handle<Value> New(const CpuProfile* profile);
13+
14+
private:
15+
static Handle<Value> GetUid(Local<String> property, const AccessorInfo& info);
16+
static Handle<Value> GetTitle(Local<String> property, const AccessorInfo& info);
17+
static Handle<Value> GetTopRoot(Local<String> property, const AccessorInfo& info);
18+
static Handle<Value> GetBottomRoot(Local<String> property, const AccessorInfo& info);
19+
static Handle<Value> Delete(const Arguments& args);
20+
static void Initialize();
21+
static Persistent<ObjectTemplate> profile_template_;
22+
};
23+
24+
} //namespace nodex
25+
#endif // NODE_PROFILE_

0 commit comments

Comments
 (0)