Skip to content
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

Merged
merged 15 commits into from
Oct 19, 2017

Conversation

nolanmar511
Copy link
Contributor

No description provided.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Oct 9, 2017
import {serializeCpuProfile} from './profile-serializer';
const cpuProfiler = require('bindings')('cpu_profiler');

export class CpuProfiler {

This comment was marked as spam.

@nolanmar511 nolanmar511 force-pushed the cpu-profiler branch 3 times, most recently from 30f1459 to a960905 Compare October 10, 2017 17:12
@nolanmar511 nolanmar511 force-pushed the cpu-profiler branch 3 times, most recently from 6e39349 to 5c0b1b2 Compare October 11, 2017 14:45
Copy link
Contributor

@ofrobots ofrobots left a 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.

}

// clears fields used to build a profile.
private reset() {

This comment was marked as spam.

This comment was marked as spam.

@@ -0,0 +1,44 @@
import {perftools} from '../profile';

This comment was marked as spam.

// True when the profiler is actively profiling.
private profiling: boolean;

constructor(samplingInterval: number) {

This comment was marked as spam.

* stack - the stack trace to the current node.
*/
private serializeNode(node: WallProfileNode, stack: Stack) {
let that = this;

This comment was marked as spam.

}, profileDuration);
});
}
return Promise.reject(new Error('already profiling with WallProfiler'));

This comment was marked as spam.


// 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.

that.profiling = true;
wallProfiler.startProfiling('', true);
return new Promise(function(resolve) {
setTimeout(function() {

This comment was marked as spam.

@@ -0,0 +1,135 @@
import {perftools} from '../src/profile';

This comment was marked as spam.

This comment was marked as spam.

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.

This comment was marked as spam.

This comment was marked as spam.

@aalexand
Copy link
Contributor

@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.

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.

@nolanmar511
Copy link
Contributor Author

PTAL
(still trying to figure out why gts check fails, which is why travis fails)

@nolanmar511 nolanmar511 force-pushed the cpu-profiler branch 6 times, most recently from b6ea041 to d525007 Compare October 12, 2017 23:51
@codecov
Copy link

codecov bot commented Oct 14, 2017

Codecov Report

❗ No coverage uploaded for pull request base (master@5dd69cf). Click here to learn what that means.
The diff coverage is 98.33%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master      #11   +/-   ##
=========================================
  Coverage          ?   98.41%           
=========================================
  Files             ?        6           
  Lines             ?      126           
  Branches          ?        7           
=========================================
  Hits              ?      124           
  Misses            ?        2           
  Partials          ?        0
Impacted Files Coverage Δ
test/profile-for-test.ts 100% <100%> (ø)
src/profilers/time-profiler.ts 100% <100%> (ø)
test/test-time-profiler.ts 100% <100%> (ø)
test/test-profile-serializer.ts 100% <100%> (ø)
src/profilers/profile-serializer.ts 96.42% <96.42%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5dd69cf...54efc86. Read the comment docs.

@nolanmar511
Copy link
Contributor Author

PTAL

// 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.

period: sampleInterval
};

/* Adds samples from a node and it's children to the fields tracking

This comment was marked as spam.

samples.push(sample);
}
for (let child of node.children) {
serializeNode(child, stack);

This comment was marked as spam.

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.

}

function getLocation(node: TimeProfileNode): perftools.profiles.Location {
const id = node.callUid;

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


// Returns true if the TimeProfiler is currently profiling and false
// otherwise.
isRunning(): boolean {

This comment was marked as spam.

return serializeTimeProfile(result, this.samplingInterval);
}

// Returns true if the TimeProfiler is currently profiling and false

This comment was marked as spam.

return f;
}

function getSampleValueType(): perftools.profiles.ValueType {

This comment was marked as spam.

@@ -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.

This comment was marked as spam.

throw new Error('already profiling with TimeProfiler');
}
this.profiling = true;
timeProfiler.startProfiling('', true);

This comment was marked as spam.

Copy link
Contributor

@ofrobots ofrobots left a 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.

@@ -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.

}

function getLocation(node: TimeProfileNode): perftools.profiles.Location {
const id = node.callUid;

This comment was marked as spam.

@nolanmar511
Copy link
Contributor Author

PTAL

* @param stack - the stack trace to the current node.
*/
function serializeNode(root: TimeProfileNode) {
let nodes = [root];

This comment was marked as spam.

@nolanmar511 nolanmar511 force-pushed the cpu-profiler branch 3 times, most recently from e258e4f to bbe21f8 Compare October 18, 2017 14:56
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.

@nolanmar511
Copy link
Contributor Author

PTAL

@nolanmar511 nolanmar511 merged commit 1bb807e into googleapis:master Oct 19, 2017
@@ -0,0 +1,145 @@
import {perftools} from '../profile';

This comment was marked as spam.

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.

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.

}

/**
* Converts v8 Profile into profile with profile format used by Stackdriver

This comment was marked as spam.

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.

name: name,
systemName: name,
filename: getIndexOrAdd(node.scriptResourceName || '(unknown)', strings)
// start_line

This comment was marked as spam.

if (f !== undefined) {
return f;
}
const name = getIndexOrAdd(node.functionName || '(anonymous)', strings);

This comment was marked as spam.

* @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.

@@ -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.

/** 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.

@nolanmar511 nolanmar511 deleted the cpu-profiler branch December 21, 2017 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants