Skip to content

Commit

Permalink
Merge pull request #20 from sidorares/0.11.x
Browse files Browse the repository at this point in the history
0.11.x
  • Loading branch information
sidorares committed Nov 20, 2014
2 parents 5676256 + 678d9a1 commit ecc2ae7
Show file tree
Hide file tree
Showing 4 changed files with 1,825 additions and 16 deletions.
29 changes: 24 additions & 5 deletions lib/logreader.js
Expand Up @@ -143,17 +143,36 @@ LogReader.prototype.dispatchLogRow_ = function(fields) {
return;
}

// special case so we can parse v8.log from both 0.10 and 0.11
// after first 'code-creation' with less than 5 fields we assume that it's from
// v8 3.14.5.9 and 'kind' field is missing from second position
// ( present in v8 3.26.33 profile, node v0.11+ )
if (command == 'code-creation' && fields.length <= 5) {
if (typeof dispatch.codeCreationKind == "undefined") {
dispatch.codeCreationKind = false;
dispatch.parsers = [null, 'void', parseInt, parseInt, null, 'var-args'];
}
}

// Parse fields.
var parsedFields = [];
for (var i = 0; i < dispatch.parsers.length; ++i) {
var parser = dispatch.parsers[i];
var fieldIndex = 1;
var parserIndex = 0;
var parser;

for ( ;parserIndex < dispatch.parsers.length; ++fieldIndex, ++parserIndex) {
parser = dispatch.parsers[parserIndex];
if (parser === null) {
parsedFields.push(fields[1 + i]);
parsedFields.push(fields[fieldIndex]);
} else if (typeof parser == 'function') {
parsedFields.push(parser(fields[1 + i]));
parsedFields.push(parser(fields[fieldIndex]));
} else if (parser === 'void') {
// add undefined to parameters, but don't consume field
parsedFields.push(void(0));
--fieldIndex;
} else {
// var-args
parsedFields.push(fields.slice(1 + i));
parsedFields.push(fields.slice(fieldIndex));
break;
}
}
Expand Down
102 changes: 91 additions & 11 deletions lib/tickprocessor.js
Expand Up @@ -31,6 +31,12 @@ var ProfileView = require('./profile_view');
var print = console.log.bind(console);
var fs = require('fs');

var os = {
system: function(name, args) {
return require('child_process').execSync(name + ' ' + args.join(' ')).toString();
}
}

function processFileLines(fileName, processLine, done) {
var logStream = fs.createReadStream(fileName);
var lineStream = require('byline').createStream(logStream);
Expand Down Expand Up @@ -85,7 +91,7 @@ function parseState(s) {
function SnapshotLogProcessor(ignoreUnknown) {
LogReader.call(this, {
'code-creation': {
parsers: [null, parseInt, parseInt, null, 'var-args'],
parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
processor: this.processCodeCreation },
'code-move': { parsers: [parseInt, parseInt],
processor: this.processCodeMove },
Expand Down Expand Up @@ -120,7 +126,7 @@ inherits(SnapshotLogProcessor, LogReader);


SnapshotLogProcessor.prototype.processCodeCreation = function(
type, start, size, name, maybe_func) {
type, kind, start, size, name, maybe_func) {
if (maybe_func.length) {
var funcAddr = parseInt(maybe_func[0]);
var state = parseState(maybe_func[1]);
Expand Down Expand Up @@ -163,12 +169,15 @@ function TickProcessor(
callGraphSize,
ignoreUnknown,
stateFilter,
snapshotLogProcessor) {
snapshotLogProcessor,
distortion,
range,
sourceMap) {
LogReader.call(this, {
'shared-library': { parsers: [null, parseInt, parseInt],
processor: this.processSharedLibrary },
'code-creation': {
parsers: [null, parseInt, parseInt, null, 'var-args'],
parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
processor: this.processCodeCreation },
'code-move': { parsers: [parseInt, parseInt],
processor: this.processCodeMove },
Expand All @@ -186,6 +195,10 @@ function TickProcessor(
processor: this.processHeapSampleBegin },
'heap-sample-end': { parsers: [null, null],
processor: this.processHeapSampleEnd },
'timer-event-start' : { parsers: [null, null, null],
processor: this.advanceDistortion },
'timer-event-end' : { parsers: [null, null, null],
processor: this.advanceDistortion },
// Ignored events.
'profiler': null,
'function-creation': null,
Expand All @@ -202,10 +215,22 @@ function TickProcessor(
this.ignoreUnknown_ = ignoreUnknown;
this.stateFilter_ = stateFilter;
this.snapshotLogProcessor_ = snapshotLogProcessor;
this.sourceMap = sourceMap;
this.deserializedEntriesNames_ = [];
var ticks = this.ticks_ =
{ total: 0, unaccounted: 0, excluded: 0, gc: 0 };

distortion = parseInt(distortion);
// Convert picoseconds to nanoseconds.
this.distortion_per_entry = isNaN(distortion) ? 0 : (distortion / 1000);
this.distortion = 0;
var rangelimits = range ? range.split(",") : [];
var range_start = parseInt(rangelimits[0]);
var range_end = parseInt(rangelimits[1]);
// Convert milliseconds to nanoseconds.
this.range_start = isNaN(range_start) ? -Infinity : (range_start * 1000);
this.range_end = isNaN(range_end) ? Infinity : (range_end * 1000)

V8Profile.prototype.handleUnknownCode = function(
operation, addr, opt_stackPos) {
if (ignoreUnknown) return;
Expand Down Expand Up @@ -245,7 +270,8 @@ TickProcessor.VmStates = {
GC: 1,
COMPILER: 2,
OTHER: 3,
EXTERNAL: 4
EXTERNAL: 4,
IDLE: 5
};


Expand Down Expand Up @@ -320,7 +346,7 @@ TickProcessor.prototype.processSharedLibrary = function(


TickProcessor.prototype.processCodeCreation = function(
type, start, size, name, maybe_func) {
type, kind, start, size, name, maybe_func) {
name = this.deserializedEntriesNames_[start] || name;
if (maybe_func.length) {
var funcAddr = parseInt(maybe_func[0]);
Expand Down Expand Up @@ -360,11 +386,16 @@ TickProcessor.prototype.includeTick = function(vmState) {
};

TickProcessor.prototype.processTick = function(pc,
sp,
ns_since_start,
is_external_callback,
tos_or_external_callback,
vmState,
stack) {
this.distortion += this.distortion_per_entry;
ns_since_start -= this.distortion;
if (ns_since_start < this.range_start || ns_since_start > this.range_end) {
return;
}
this.ticks_.total++;
if (vmState == TickProcessor.VmStates.GC) this.ticks_.gc++;
if (!this.includeTick(vmState)) {
Expand All @@ -391,6 +422,11 @@ TickProcessor.prototype.processTick = function(pc,
};


TickProcessor.prototype.advanceDistortion = function() {
this.distortion += this.distortion_per_entry;
}


TickProcessor.prototype.processHeapSampleBegin = function(space, state, ticks) {
if (space != 'Heap') return;
this.currentProducerProfile_ = new CallTree();
Expand Down Expand Up @@ -549,17 +585,52 @@ TickProcessor.prototype.processProfile = function(
}
};

TickProcessor.prototype.getLineAndColumn = function(name) {
var re = /:([0-9]+):([0-9]+)$/;
var array = re.exec(name);
if (!array) {
return null;
}
return {line: array[1], column: array[2]};
}

TickProcessor.prototype.hasSourceMap = function() {
return this.sourceMap != null;
};


TickProcessor.prototype.formatFunctionName = function(funcName) {
if (!this.hasSourceMap()) {
return funcName;
}
var lc = this.getLineAndColumn(funcName);
if (lc == null) {
return funcName;
}
// in source maps lines and columns are zero based
var lineNumber = lc.line - 1;
var column = lc.column - 1;
var entry = this.sourceMap.findEntry(lineNumber, column);
var sourceFile = entry[2];
var sourceLine = entry[3] + 1;
var sourceColumn = entry[4] + 1;

return sourceFile + ':' + sourceLine + ':' + sourceColumn + ' -> ' + funcName;
};

TickProcessor.prototype.printEntries = function(
profile, nonLibTicks, filterP) {
var that = this;
this.processProfile(profile, filterP, function (rec) {
if (rec.selfTime == 0) return;
var nonLibPct = nonLibTicks != null ?
rec.selfTime * 100.0 / nonLibTicks : 0.0;
var funcName = that.formatFunctionName(rec.internalFuncName);

print(' ' + padLeft(rec.selfTime, 5) + ' ' +
padLeft(rec.selfPercent.toFixed(1), 5) + '% ' +
padLeft(nonLibPct.toFixed(1), 5) + '% ' +
rec.internalFuncName);
funcName);
});
};

Expand All @@ -571,9 +642,10 @@ TickProcessor.prototype.printHeavyProfile = function(profile, opt_indent) {
this.processProfile(profile, function() { return true; }, function (rec) {
// Cut off too infrequent callers.
if (rec.parentTotalPercent < TickProcessor.CALL_PROFILE_CUTOFF_PCT) return;
var funcName = self.formatFunctionName(rec.internalFuncName);
print(' ' + padLeft(rec.totalTime, 5) + ' ' +
padLeft(rec.parentTotalPercent.toFixed(1), 5) + '% ' +
indentStr + rec.internalFuncName);
indentStr + funcName);
// Limit backtrace depth.
if (indent < 2 * self.callGraphSize_) {
self.printHeavyProfile(rec.children, indent + 2);
Expand Down Expand Up @@ -846,7 +918,13 @@ function ArgumentsProcessor(args) {
'--target': ['targetRootFS', '',
'Specify the target root directory for cross environment'],
'--snapshot-log': ['snapshotLogFileName', 'snapshot.log',
'Specify snapshot log file to use (e.g. --snapshot-log=snapshot.log)']
'Specify snapshot log file to use (e.g. --snapshot-log=snapshot.log)'],
'--range': ['range', 'auto,auto',
'Specify the range limit as [start],[end]'],
'--distortion': ['distortion', 0,
'Specify the logging overhead in picoseconds'],
'--source-map': ['sourceMap', null,
'Specify the source map that should be used for output']
};
this.argsDispatch_['--js'] = this.argsDispatch_['-j'];
this.argsDispatch_['--gc'] = this.argsDispatch_['-g'];
Expand All @@ -865,7 +943,9 @@ ArgumentsProcessor.DEFAULTS = {
ignoreUnknown: false,
separateIc: false,
targetRootFS: '',
nm: 'nm'
nm: 'nm',
range: 'auto,auto',
distortion: 0
};


Expand Down
8 changes: 8 additions & 0 deletions test/generate.js
@@ -0,0 +1,8 @@
function slow() {
var res=0;
for (var i=0; i < 10000000; ++i)
res += i;
return res;
}

console.log(slow() + slow() + slow());

0 comments on commit ecc2ae7

Please sign in to comment.