-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add local CPU profile collection #11
Conversation
da5fdf7
to
2563c01
Compare
src/profilers/cpu-profiler.ts
Outdated
import {serializeCpuProfile} from './profile-serializer'; | ||
const cpuProfiler = require('bindings')('cpu_profiler'); | ||
|
||
export class CpuProfiler { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
30f1459
to
a960905
Compare
6e39349
to
5c0b1b2
Compare
5c0b1b2
to
e4a68c9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left an initial set of comments. PTAL.
Side note: Most people in the Node.js community will be confused by the phrasing 'Wall Profile', specially in configuration. People are familiar with the V8 CPU Profiler that is also available through dev tools. I understand the difference in terminology that the cloud profiler is using, but in the node community 'wall profiler' will need a lot of explanation for people to understand.
@@ -0,0 +1,145 @@ | |||
import {perftools} from '../profile'; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/profile-serializer.ts
Outdated
} | ||
|
||
// clears fields used to build a profile. | ||
private reset() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/wall-profiler.ts
Outdated
@@ -0,0 +1,44 @@ | |||
import {perftools} from '../profile'; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/wall-profiler.ts
Outdated
// True when the profiler is actively profiling. | ||
private profiling: boolean; | ||
|
||
constructor(samplingInterval: number) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/profile-serializer.ts
Outdated
* stack - the stack trace to the current node. | ||
*/ | ||
private serializeNode(node: WallProfileNode, stack: Stack) { | ||
let that = this; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/wall-profiler.ts
Outdated
}, profileDuration); | ||
}); | ||
} | ||
return Promise.reject(new Error('already profiling with WallProfiler')); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/wall-profiler.ts
Outdated
|
||
// Collects a profile for the duration, in milliseconds, specified by | ||
// profileDuration. | ||
// Returns a promise which will resolve to the collected profile. |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/wall-profiler.ts
Outdated
that.profiling = true; | ||
wallProfiler.startProfiling('', true); | ||
return new Promise(function(resolve) { | ||
setTimeout(function() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
@@ -0,0 +1,135 @@ | |||
import {perftools} from '../src/profile'; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
package.json
Outdated
@@ -5,7 +5,7 @@ | |||
"main": "build/src/index.js", | |||
"scripts": { | |||
"install": "node-gyp rebuild", | |||
"test": "true", | |||
"test": "mocha build/test/test-*.js", |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
@ofrobots We could keep the "CPU profiler" terminology in the API here but we'll still need to send these profiles as of "wall" profiling type in the Cloud Profiler speak to be consistent with the data agents for other languages produce. Those use "CPU" profiling type to describe profiles where samples represent the actual CPU time spent by the program. |
2878931
to
0976a56
Compare
src/profilers/wall-profiler.ts
Outdated
return Promise.reject(new Error('already profiling with WallProfiler')); | ||
this.profiling = true; | ||
wallProfiler.startProfiling('', true); | ||
return delay(profileDuration).then(() => { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
f03d9b8
to
1be0b8c
Compare
PTAL |
b6ea041
to
d525007
Compare
d525007
to
7f2d979
Compare
701d195
to
7515fd7
Compare
7515fd7
to
b12b092
Compare
Codecov Report
@@ Coverage Diff @@
## master #11 +/- ##
=========================================
Coverage ? 98.41%
=========================================
Files ? 6
Lines ? 126
Branches ? 7
=========================================
Hits ? 124
Misses ? 2
Partials ? 0
Continue to review full report at Codecov.
|
PTAL |
12045b4
to
1a3ef77
Compare
src/profilers/profile-serializer.ts
Outdated
// A stack of function UIDs. | ||
type Stack = Array<number>; | ||
|
||
// Converts v8 Profile into profile with profile format used by Stackdriver |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/profile-serializer.ts
Outdated
period: sampleInterval | ||
}; | ||
|
||
/* Adds samples from a node and it's children to the fields tracking |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/profile-serializer.ts
Outdated
samples.push(sample); | ||
} | ||
for (let child of node.children) { | ||
serializeNode(child, stack); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/profile-serializer.ts
Outdated
function getLocation(node: TimeProfileNode): perftools.profiles.Location { | ||
const id = node.callUid; | ||
if (locationMap.has(id)) { | ||
return locationMap.get(id) as perftools.profiles.Location; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/profile-serializer.ts
Outdated
} | ||
|
||
function getLocation(node: TimeProfileNode): perftools.profiles.Location { | ||
const id = node.callUid; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/time-profiler.ts
Outdated
|
||
// Returns true if the TimeProfiler is currently profiling and false | ||
// otherwise. | ||
isRunning(): boolean { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/time-profiler.ts
Outdated
return serializeTimeProfile(result, this.samplingInterval); | ||
} | ||
|
||
// Returns true if the TimeProfiler is currently profiling and false |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/profile-serializer.ts
Outdated
return f; | ||
} | ||
|
||
function getSampleValueType(): perftools.profiles.ValueType { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
bindings/time-profiler.cc
Outdated
@@ -19,7 +19,7 @@ | |||
|
|||
using namespace v8; | |||
|
|||
Local<Value> TranslateCpuProfileNode(const CpuProfileNode* node) { | |||
Local<Value> TranslateTimeProfileNode(const CpuProfileNode* node) { | |||
// TODO: Implement unimplemented interface |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/time-profiler.ts
Outdated
throw new Error('already profiling with TimeProfiler'); | ||
} | ||
this.profiling = true; | ||
timeProfiler.startProfiling('', true); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good. From what I can see the main outstanding issue is the comment from @aalexand about recursion.
bindings/time-profiler.cc
Outdated
@@ -19,7 +19,7 @@ | |||
|
|||
using namespace v8; | |||
|
|||
Local<Value> TranslateCpuProfileNode(const CpuProfileNode* node) { | |||
Local<Value> TranslateTimeProfileNode(const CpuProfileNode* node) { | |||
// TODO: Implement unimplemented interface |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/profilers/profile-serializer.ts
Outdated
} | ||
|
||
function getLocation(node: TimeProfileNode): perftools.profiles.Location { | ||
const id = node.callUid; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
PTAL |
src/profilers/profile-serializer.ts
Outdated
* @param stack - the stack trace to the current node. | ||
*/ | ||
function serializeNode(root: TimeProfileNode) { | ||
let nodes = [root]; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
e258e4f
to
bbe21f8
Compare
bbe21f8
to
1735b3e
Compare
src/profilers/profile-serializer.ts
Outdated
let node = nodes.pop(); | ||
let stack = stacks.pop(); | ||
if (node !== undefined && stack !== undefined) { | ||
let entries: {node: TimeProfileNode, stack: number[]}[] = []; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
f4b9ce0
to
54efc86
Compare
PTAL |
@@ -0,0 +1,145 @@ | |||
import {perftools} from '../profile'; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
import {perftools} from '../profile'; | ||
import {getIndexOrAdd} from '../util'; | ||
import {TimeProfile, TimeProfileNode} from '../v8-types'; | ||
// A stack of function UIDs. |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
import {perftools} from '../profile'; | ||
import {getIndexOrAdd} from '../util'; | ||
import {TimeProfile, TimeProfileNode} from '../v8-types'; | ||
// A stack of function UIDs. |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
} | ||
|
||
/** | ||
* Converts v8 Profile into profile with profile format used by Stackdriver |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
let samples: Array<perftools.profiles.Sample> = []; | ||
let locations: Array<perftools.profiles.Location> = []; | ||
let functions: Array<perftools.profiles.Function> = []; | ||
let locationMap: Map<number, perftools.profiles.Location> = new Map(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
name: name, | ||
systemName: name, | ||
filename: getIndexOrAdd(node.scriptResourceName || '(unknown)', strings) | ||
// start_line |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
if (f !== undefined) { | ||
return f; | ||
} | ||
const name = getIndexOrAdd(node.functionName || '(anonymous)', strings); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
* @param durationMillis - time in milliseconds for which to collect profile. | ||
*/ | ||
async profile(durationMillis: number): Promise<perftools.profiles.IProfile> { | ||
const runName = 'stackdriver-profiler-' + Date.now() + '-' + Math.random(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
@@ -16,21 +16,21 @@ | |||
|
|||
// Type Definitions based on implementation in bindings/ | |||
|
|||
export interface CpuProfile { | |||
export interface TimeProfile { | |||
/** Time in nanoseconds at which profile was stopped. */ | |||
endTime: number; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
/** Time in nanoseconds at which profile was stopped. */ | ||
endTime: number; | ||
topDownRoot: CpuProfileNode; | ||
topDownRoot: TimeProfileNode; | ||
/** Time in nanoseconds at which profile was started. */ | ||
startTime: number; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
No description provided.