cpuprofilify
Advanced tools
Comparing version 0.4.0 to 1.0.0
@@ -17,3 +17,3 @@ usage: cat trace.txt | cpuprofilify <options> > my.cpuprofile | ||
--type type of input `perf|dtrace|instruments`. If not supplied it will be detected. | ||
--type type of input `perf|dtrace`. If not supplied it will be detected. | ||
--help print this help | ||
@@ -20,0 +20,0 @@ |
114
index.js
@@ -1,15 +0,13 @@ | ||
'use strict'; | ||
var filterInternals = require('trace-filter-internals') | ||
, traceUtil = require('./lib/trace-util') | ||
, getConverter = require('./lib/get-converter') | ||
, resolveSymbols = require('./lib/resolve-symbols') | ||
, resolveSymbolsFromMap = require('./lib/resolve-symbols-from-map') | ||
, xtend = require('xtend') | ||
, inherits = require('inherits') | ||
, EventEmitter = require('events').EventEmitter | ||
var traceUtil = require('./lib/trace-util') | ||
var getConverter = require('./lib/get-converter') | ||
var resolveSymbols = require('./lib/resolve-symbols') | ||
var resolveSymbolsFromMap = require('./lib/resolve-symbols-from-map') | ||
var xtend = require('xtend') | ||
var inherits = require('inherits') | ||
var EventEmitter = require('events').EventEmitter | ||
/** | ||
* Creates new CpuProfilifier | ||
* | ||
* | ||
* @name CpuProfilifier | ||
@@ -19,12 +17,12 @@ * @function | ||
function CpuProfilifier() { | ||
if (!(this instanceof CpuProfilifier)) return new CpuProfilifier(); | ||
EventEmitter.call(this); | ||
if (!(this instanceof CpuProfilifier)) return new CpuProfilifier() | ||
EventEmitter.call(this) | ||
} | ||
inherits(CpuProfilifier, EventEmitter); | ||
inherits(CpuProfilifier, EventEmitter) | ||
var proto = CpuProfilifier.prototype; | ||
module.exports = CpuProfilifier; | ||
var proto = CpuProfilifier.prototype | ||
module.exports = CpuProfilifier | ||
proto.convert = | ||
proto.convert = | ||
@@ -35,5 +33,5 @@ /** | ||
* ``` | ||
* var cpuprofilifier = require('cpuprofilifier'); | ||
* var cpuprofile = cpuprofilifier().convert(trace); | ||
* fs.writeFileSync('/tmp/my.cpuprofile', JSON.stringify(cpuprofile)); | ||
* var cpuprofilifier = require('cpuprofilifier') | ||
* var cpuprofile = cpuprofilifier().convert(trace) | ||
* fs.writeFileSync('/tmp/my.cpuprofile', JSON.stringify(cpuprofile)) | ||
* ``` | ||
@@ -44,5 +42,5 @@ * | ||
* @param {Array.<String>} trace a trace generated via `perf script` or the `profile_1ms.d` DTrace script | ||
* @param {Object=} opts | ||
* @param {string} opts.map a map containing symbols information, if not given it will be read from /tmp/perf-<pid>.map. | ||
* @param {string} opts.type type of input `perf|dtrace|instruments`. If not supplied it will be detected. | ||
* @param {Object=} opts | ||
* @param {string} opts.map a map containing symbols information, if not given it will be read from /tmp/perf-<pid>.map. | ||
* @param {string} opts.type type of input `perf|dtrace`. If not supplied it will be detected. | ||
* @param {Boolean} opts.shortStack stacks that have only one line are ignored unless this flag is set | ||
@@ -57,37 +55,31 @@ * @param {Boolean} opts.optimizationinfo JS optimization info is removed unless this flag is set (default: false) | ||
function convert(trace, opts) { | ||
opts = opts || {}; | ||
this._map = opts.map; | ||
opts = opts || {} | ||
this._map = opts.map | ||
this._opts = xtend({ v8gc: true }, opts, { map: this._map ? 'was supplied' : 'was not supplied' }); | ||
this.emit('info', 'Options: %j', this._opts); | ||
this._opts = xtend({ v8gc: true }, opts, { map: this._map ? 'was supplied' : 'was not supplied' }) | ||
this.emit('info', 'Options: %j', this._opts) | ||
this._trace = trace; | ||
this._traceLen = trace.length; | ||
this._trace = trace | ||
this._traceLen = trace.length | ||
if (!this._traceLen) { | ||
this.emit('warn', 'Trace was empty, quitting'); | ||
return; | ||
this.emit('warn', 'Trace was empty, quitting') | ||
return | ||
} | ||
try { | ||
this._traceStart = traceUtil.traceStart(this._trace); | ||
try { | ||
this._traceStart = traceUtil.traceStart(this._trace) | ||
this._converterCtr = getConverter(this._trace, this._traceStart, this._opts.type); | ||
if (this._converterCtr.proto.type === 'instruments') | ||
this.emit('warn', 'You are converting an instruments callgraph.\n' + | ||
'It only contain aggregation data but no timeline.\n' + | ||
'However a timeline from 0s-5s will appear when loaded in DevTools.\n' + | ||
'It will not show the true execution order. Please be aware!'); | ||
this._resolveTraceInfo(); | ||
this._tryResolveSymbols(); | ||
this._filterInternals(); | ||
this._converterCtr = getConverter(this._trace, this._traceStart, this._opts.type) | ||
this._resolveTraceInfo() | ||
this._tryResolveSymbols() | ||
this._filterInternals() | ||
var converter = this._converterCtr(this._filtered, this._traceStart, this._opts); | ||
this.emit('info', 'Converting trace of length %d', this._filteredLen); | ||
var converted = converter.convert(); | ||
this.emit('info', 'Success!'); | ||
return converted; | ||
var converter = this._converterCtr(this._filtered, this._traceStart, this._opts) | ||
this.emit('info', 'Converting trace of length %d', this._filteredLen) | ||
var converted = converter.convert() | ||
this.emit('info', 'Success!') | ||
return converted | ||
} catch (err) { | ||
this.emit('error', err); | ||
this.emit('error', err) | ||
} | ||
@@ -97,17 +89,17 @@ } | ||
proto._tryResolveSymbols = function _tryResolveSymbols() { | ||
var res = this._map ? resolveSymbolsFromMap(this._map, this._trace) : resolveSymbols(this.traceInfo.pid, this._trace); | ||
if (res.resolved) { | ||
this.emit('info', 'Resolved symbols in trace.'); | ||
this._trace = res.resolved; | ||
return; | ||
var res = this._map ? resolveSymbolsFromMap(this._map, this._trace) : resolveSymbols(this.traceInfo.pid, this._trace) | ||
if (res.resolved) { | ||
this.emit('info', 'Resolved symbols in trace.') | ||
this._trace = res.resolved | ||
return | ||
} | ||
this.emit('warn', res.reason); | ||
this.emit('warn', res.reason) | ||
} | ||
proto._resolveTraceInfo = function _resolveTraceInfo() { | ||
var converter = this._converterCtr(this._trace, this._traceStart, this._opts); | ||
converter._parseTraceInfo(this._trace[this._traceStart], true); | ||
var converter = this._converterCtr(this._trace, this._traceStart, this._opts) | ||
converter._parseTraceInfo(this._trace[this._traceStart], true) | ||
this.traceInfo = { | ||
this.traceInfo = { | ||
process : converter._process | ||
@@ -123,7 +115,7 @@ , pid : converter._pid | ||
proto._filterInternals = function _filterInternals() { | ||
this._filtered = this._trace; | ||
this._filtered = filterInternals(this._trace, this._opts); | ||
this._filteredLen = this._filtered.length; | ||
this._filtered = this._trace | ||
this._filtered = filterInternals(this._trace, this._opts) | ||
this._filteredLen = this._filtered.length | ||
this.emit('info', 'Filtered %d internals from given trace', this._traceLen - this._filteredLen); | ||
this.emit('info', 'Filtered %d internals from given trace', this._traceLen - this._filteredLen) | ||
} |
@@ -1,9 +0,7 @@ | ||
'use strict'; | ||
var inherits = require('inherits') | ||
, Converter = require('./converter') | ||
var Converter = require('./converter') | ||
function DTraceConverter(trace, traceStart, opts) { | ||
if (!(this instanceof DTraceConverter)) return new DTraceConverter(trace, traceStart, opts); | ||
Converter.call(this, trace, traceStart, opts); | ||
if (!(this instanceof DTraceConverter)) return new DTraceConverter(trace, traceStart, opts) | ||
Converter.call(this, trace, traceStart, opts) | ||
@@ -13,11 +11,12 @@ this._frameProcessRegex = new RegExp('^(' + this._process + '|node)`') | ||
inherits(DTraceConverter, Converter); | ||
var proto = DTraceConverter.prototype; | ||
inherits(DTraceConverter, Converter) | ||
var proto = DTraceConverter.prototype | ||
proto._framePartsRegex = /(.+?) (.+?):(\d+)$/; | ||
proto._framePartsRegex = /(.+?) (.+?):(\d+)$/ | ||
// Overrides | ||
proto._parseFrame = function _parseFrame(frame) { | ||
var m = frame.match(this._framePartsRegex); | ||
if (!m) return { | ||
var m = frame.match(this._framePartsRegex) | ||
if (!m) { | ||
return { | ||
functionName : frame | ||
@@ -28,14 +27,15 @@ , url : '' | ||
} | ||
} | ||
var functionName = m[1] | ||
, script = m[2] | ||
, lineNumber = m[3] | ||
var scriptId = this._scriptIds[script]; | ||
if (!scriptId) { | ||
scriptId = this._scriptId++; | ||
this._scriptIds[script] = scriptId; | ||
var script = m[2] | ||
var lineNumber = m[3] | ||
var scriptId = this._scriptIds[script] | ||
if (!scriptId) { | ||
scriptId = this._scriptId++ | ||
this._scriptIds[script] = scriptId | ||
} | ||
if (/^[~*]\s*$/.test(functionName)) functionName += ' <anonymous>'; | ||
if (/^[~*]\s*$/.test(functionName)) functionName += ' <anonymous>' | ||
return { | ||
@@ -50,15 +50,15 @@ functionName : functionName | ||
proto._parseTraceInfo = function _parseTraceInfo(line, isStart) { | ||
var parts = line.split(/\s+/); | ||
var parts = line.split(/\s+/) | ||
if (!isStart) { | ||
this._endTime = (parts[2] && parts[2].slice(0, -1)) || '0'; | ||
return; | ||
if (!isStart) { | ||
this._endTime = (parts[2] && parts[2].slice(0, -1)) || '0' | ||
return | ||
} | ||
if (this._startTime && this._process && this._pid && this._type) return; | ||
if (this._startTime && this._process && this._pid && this._type) return | ||
this._startTime = (parts[2] && parts[2].slice(0, -1)) || '0.0'; | ||
this._startTime = (parts[2] && parts[2].slice(0, -1)) || '0.0' | ||
this._process = parts[0]; | ||
this._pid = parts[1]; | ||
this._type = parts[3] || ''; | ||
this._process = parts[0] | ||
this._pid = parts[1] | ||
this._type = parts[3] || '' | ||
} | ||
@@ -68,3 +68,3 @@ | ||
return this.removeOptimizationInfo( | ||
frame | ||
frame | ||
.trim() | ||
@@ -78,6 +78,6 @@ .replace(this._frameAddressRegex, '') | ||
proto._adjustTime = function _adjustTime(t) { | ||
var s = t.toString(); | ||
var s = t.toString() | ||
// 0 is a special case | ||
if (s.length < 5) return s; | ||
return s.slice(0, -3) + '.' + s.slice(4); | ||
if (s.length < 5) return s | ||
return s.slice(0, -3) + '.' + s.slice(4) | ||
} | ||
@@ -88,6 +88,6 @@ | ||
proto._frameJSAddressRegex = /0x[0-9a-fA-F]+( LazyCompile:| Function:| Script:){0,1}/ | ||
proto.type = 'dtrace'; | ||
proto.type = 'dtrace' | ||
exports = module.exports = DTraceConverter; | ||
exports.ctor = DTraceConverter; | ||
exports.proto = proto; | ||
exports = module.exports = DTraceConverter | ||
exports.ctor = DTraceConverter | ||
exports.proto = proto |
@@ -1,25 +0,23 @@ | ||
'use strict'; | ||
var inherits = require('inherits') | ||
, Converter = require('./converter') | ||
, DTraceConverter = require('./converter-dtrace').proto | ||
var Converter = require('./converter') | ||
var DTraceConverter = require('./converter-dtrace').proto | ||
function PerfConverter(trace, traceStart, opts) { | ||
if (!(this instanceof PerfConverter)) return new PerfConverter(trace, traceStart, opts); | ||
Converter.call(this, trace, traceStart, opts); | ||
if (!(this instanceof PerfConverter)) return new PerfConverter(trace, traceStart, opts) | ||
Converter.call(this, trace, traceStart, opts) | ||
} | ||
inherits(PerfConverter, Converter); | ||
var proto = PerfConverter.prototype; | ||
inherits(PerfConverter, Converter) | ||
var proto = PerfConverter.prototype | ||
proto._frameRegex = /^\w+\s+(?:LazyCompile:|Function:|Script:){0,1}(.+?)\W\(\S+\)$/; | ||
proto._framePartsRegex = /^(.+?)([\S\.]+):(\d+)$/; | ||
proto._frameRegex = /^\w+\s+(?:LazyCompile:|Function:|Script:){0,1}(.+?)\W\(\S+\)$/ | ||
proto._framePartsRegex = /^(.+?)([\S.]+):(\d+)$/ | ||
// Overrides | ||
proto._parseFrame = function _parseFrame(frame) { | ||
return DTraceConverter._parseFrame.call(this, frame); | ||
return DTraceConverter._parseFrame.call(this, frame) | ||
} | ||
proto._parseTraceInfo = function _parseTraceInfo(line, isStart) { | ||
DTraceConverter._parseTraceInfo.call(this, line, isStart); | ||
DTraceConverter._parseTraceInfo.call(this, line, isStart) | ||
} | ||
@@ -29,3 +27,3 @@ | ||
return this.removeOptimizationInfo( | ||
frame | ||
frame | ||
.trim() | ||
@@ -40,6 +38,6 @@ .replace(this._frameRegex, '$1') | ||
proto.type = 'perf'; | ||
proto.type = 'perf' | ||
exports = module.exports = PerfConverter; | ||
exports.ctor = PerfConverter; | ||
exports.proto = proto; | ||
exports = module.exports = PerfConverter | ||
exports.ctor = PerfConverter | ||
exports.proto = proto |
@@ -1,50 +0,48 @@ | ||
'use strict'; | ||
var cpuprofile = require('./cpuprofile') | ||
, traceUtil = require('./trace-util') | ||
, roi = require('./remove-optimization-info') | ||
var traceUtil = require('./trace-util') | ||
var roi = require('./remove-optimization-info') | ||
function Converter(trace, traceStart, opts) { | ||
if (!(this instanceof Converter)) return new Converter(trace, traceStart, opts); | ||
opts = opts || {}; | ||
if (!(this instanceof Converter)) return new Converter(trace, traceStart, opts) | ||
opts = opts || {} | ||
this._trace = traceUtil.normalizeEmptyLines(trace); | ||
this._traceStart = traceStart; | ||
this._trace = traceUtil.normalizeEmptyLines(trace) | ||
this._traceStart = traceStart | ||
this._id = 0; | ||
this._scriptId = 0; | ||
this._scriptIds = {}; | ||
this._id = 0 | ||
this._scriptId = 0 | ||
this._scriptIds = {} | ||
this._process = undefined; | ||
this._pid = undefined; | ||
this._type = undefined; | ||
this._startTime = undefined; | ||
this._endTime = undefined; | ||
this._process = undefined | ||
this._pid = undefined | ||
this._type = undefined | ||
this._startTime = undefined | ||
this._endTime = undefined | ||
this._parseTraceInfo(trace[this._traceStart], true); | ||
this._parseTraceInfo(trace[this._traceStart], true) | ||
this._head = cpuprofile.createHead(this._process, this._scriptId++); | ||
this._samples = []; | ||
this._head = cpuprofile.createHead(this._process, this._scriptId++) | ||
this._samples = [] | ||
this._optimizationinfo = opts.optimizationinfo; | ||
this._shortStacks = opts.shortStacks; | ||
this._optimizationinfo = opts.optimizationinfo | ||
this._shortStacks = opts.shortStacks | ||
} | ||
var proto = Converter.prototype; | ||
var proto = Converter.prototype | ||
// Overrides | ||
proto._parseFrame = function _parseFrame(frame) { | ||
throw new Error('Need to implement _parseFrame.'); | ||
proto._parseFrame = function _parseFrame(frame) { | ||
throw new Error('Need to implement _parseFrame.') | ||
} | ||
proto._parseTraceInfo = function _parseTraceInfo(frame) { | ||
throw new Error('Need to implement _parseTraceInfo.'); | ||
proto._parseTraceInfo = function _parseTraceInfo(frame) { | ||
throw new Error('Need to implement _parseTraceInfo.') | ||
} | ||
proto._normalizeFrame = function _normalizeFrame(frame) { | ||
throw new Error('Need to implement _normalizeFrame.'); | ||
proto._normalizeFrame = function _normalizeFrame(frame) { | ||
throw new Error('Need to implement _normalizeFrame.') | ||
} | ||
proto._adjustTime = function _adjustTime(frame) { | ||
throw new Error('Need to implement _adjustTime.'); | ||
proto._adjustTime = function _adjustTime(frame) { | ||
throw new Error('Need to implement _adjustTime.') | ||
} | ||
@@ -54,60 +52,65 @@ | ||
proto.findOrCreateNode = function findOrCreateNode(parent, nextId, stackFrame) { | ||
var child; | ||
var child | ||
for (var i = 0; i < parent.children.length; i++) { | ||
child = parent.children[i] | ||
if (child._stackFrame === stackFrame) { | ||
return child; | ||
child = parent.children[i] | ||
if (child._stackFrame === stackFrame) { | ||
return child | ||
} | ||
} | ||
var opts = this._parseFrame(stackFrame); | ||
var opts = this._parseFrame(stackFrame) | ||
var node = cpuprofile.createNode(nextId, stackFrame, opts); | ||
parent.children.push(node); | ||
return node; | ||
var node = cpuprofile.createNode(nextId, stackFrame, opts) | ||
parent.children.push(node) | ||
return node | ||
} | ||
proto.objectifyStack = function objectifyStack(stackStart, stackEnd) { | ||
var parent = this._head, frame; | ||
var parent = this._head | ||
var frame | ||
// cpuprofiler children are in parent->child order while stacks have parents below children | ||
for (var i = stackEnd; i >= stackStart; i--) { | ||
frame = this._normalizeFrame(this._trace[i]); | ||
frame = this._normalizeFrame(this._trace[i]) | ||
// remove frames whose description became empty after all the cleaning up | ||
if (!frame.length) continue; | ||
if (!frame.length) continue | ||
parent = this.findOrCreateNode(parent, this._id, frame); | ||
this._id = Math.max(parent.id + 1, this._id); | ||
parent = this.findOrCreateNode(parent, this._id, frame) | ||
this._id = Math.max(parent.id + 1, this._id) | ||
} | ||
parent.hitCount++; | ||
this._samples.push(parent.id); | ||
parent.hitCount++ | ||
this._samples.push(parent.id) | ||
} | ||
proto.objectifyTrace = function objectifyTrace() { | ||
var stackStart = 0, insideStack = false, line, nextLine, nextNextLine, lastTraceInfo; | ||
var stackStart = 0 | ||
var insideStack = false | ||
var line | ||
var nextLine | ||
var nextNextLine | ||
var lastTraceInfo | ||
for (var i = this._traceStart; i < this._trace.length; i++) { | ||
line = this._trace[i]; | ||
line = this._trace[i] | ||
// right above a new stack, i.e: iojs 49959 140951795: profile-1ms: | ||
if (!insideStack && line.length && line.charAt(0) !== ' ') { | ||
// a stack may be entirely empty due to previous filtering of internals | ||
nextLine = this._trace[i + 1]; | ||
if (!nextLine || !nextLine.length) continue; | ||
nextLine = this._trace[i + 1] | ||
if (!nextLine || !nextLine.length) continue | ||
// skip stacks that have only one frame unless we want to keep those | ||
if (!this._shortStacks) { | ||
nextNextLine = this._trace[i + 2]; | ||
if (!nextNextLine || !nextNextLine.length) continue; | ||
nextNextLine = this._trace[i + 2] | ||
if (!nextNextLine || !nextNextLine.length) continue | ||
} | ||
lastTraceInfo = line; | ||
lastTraceInfo = line | ||
stackStart = i + 1; | ||
insideStack = true; | ||
} | ||
stackStart = i + 1 | ||
insideStack = true | ||
} | ||
if (insideStack && !line.length) { | ||
this.objectifyStack(stackStart, i - 1); | ||
insideStack = false; | ||
this.objectifyStack(stackStart, i - 1) | ||
insideStack = false | ||
} | ||
@@ -117,12 +120,12 @@ } | ||
// last stack had end time since it was the last tick | ||
this._parseTraceInfo(lastTraceInfo, false); | ||
return this; | ||
this._parseTraceInfo(lastTraceInfo, false) | ||
return this | ||
} | ||
proto.removeOptimizationInfo = function removeOptimizationInfo(name) { | ||
return this._optimizationinfo ? name : roi(name); | ||
return this._optimizationinfo ? name : roi(name) | ||
} | ||
proto.cpuprofile = function cpuprofile() { | ||
return { | ||
return { | ||
typeId : 'CPU ' + this._type | ||
@@ -139,7 +142,7 @@ , uid : 1 | ||
proto.convert = function convert() { | ||
return this.objectifyTrace().cpuprofile(); | ||
return this.objectifyTrace().cpuprofile() | ||
} | ||
exports = module.exports = Converter; | ||
exports.ctor = Converter; | ||
exports.proto = proto; | ||
exports = module.exports = Converter | ||
exports.ctor = Converter | ||
exports.proto = proto |
@@ -1,6 +0,4 @@ | ||
'use strict'; | ||
exports.createHead = function createHead(execname, id) { | ||
return { | ||
functionName : execname | ||
functionName : execname | ||
, url : '' | ||
@@ -10,3 +8,3 @@ , lineNumber : 0 | ||
, bailoutReason : '' | ||
, id : id | ||
, id : id | ||
, scriptId : 0 | ||
@@ -13,0 +11,0 @@ , hitCount : 0 |
@@ -1,28 +0,22 @@ | ||
'use strict'; | ||
var dtraceConverterCtr = require('./converter-dtrace') | ||
, perfConverterCtr = require('./converter-perf') | ||
, instrumentsConverterCtr = require('./converter-instruments') | ||
var perfConverterCtr = require('./converter-perf') | ||
var dtraceRegex = /^\S+ \d+ \d+: \S+:\s*$/ | ||
, perfRegex = /^\S+\s+\d+(\s+\[\d+\])?\s+\d+\.\d+:(\s+\d+)? \S+:\s*$/ | ||
, instrumentsRegex = /^Running Time, *Self,.*, *Symbol Name/ | ||
var perfRegex = /^\S+\s+\d+(\s+\[\d+])?\s+\d+\.\d+:(\s+\d+)? \S+:\s*$/ | ||
var go = module.exports = function getConverter(trace, traceStart, type) { | ||
module.exports = function getConverter(trace, traceStart, type) { | ||
if (type) { | ||
switch(type) { | ||
case 'perf' : return perfConverterCtr; | ||
case 'dtrace' : return dtraceConverterCtr; | ||
case 'instruments' : return instrumentsConverterCtr; | ||
default : throw new Error('Unknown input type : ' + type); | ||
switch (type) { | ||
case 'perf' : return perfConverterCtr | ||
case 'dtrace' : return dtraceConverterCtr | ||
default : throw new Error('Unknown input type : ' + type) | ||
} | ||
} | ||
var line = trace[traceStart]; | ||
var line = trace[traceStart] | ||
if (dtraceRegex.test(line)) return dtraceConverterCtr; | ||
if (perfRegex.test(line)) return perfConverterCtr; | ||
if (instrumentsRegex.test(line)) return instrumentsConverterCtr; | ||
if (dtraceRegex.test(line)) return dtraceConverterCtr | ||
if (perfRegex.test(line)) return perfConverterCtr | ||
throw new Error('Unable to detect input type for \n"' + line + '"'); | ||
throw new Error('Unable to detect input type for \n"' + line + '"') | ||
} |
@@ -1,10 +0,8 @@ | ||
'use strict'; | ||
var regex = /^\W*[*~]/ | ||
// replacement indicates that this was either ~ or * and also doesn't | ||
// break tools that look for ~ to identify JS | ||
, replacement = '~*' | ||
var replacement = '~*' | ||
var go = module.exports = function removeOptimizationInfo(functionName) { | ||
return functionName.replace(regex, replacement); | ||
module.exports = function removeOptimizationInfo(functionName) { | ||
return functionName.replace(regex, replacement) | ||
} |
@@ -1,10 +0,8 @@ | ||
'use strict'; | ||
var resolveJITSymbols = require('resolve-jit-symbols') | ||
var resolveJITSymbols = require('resolve-jit-symbols'); | ||
module.exports = function resolveSymbolsFromMap(map, trace) { | ||
var resolver = resolveJITSymbols(map) | ||
, resolved = resolver.resolveMulti(trace); | ||
return { resolved: resolved }; | ||
var resolved = resolver.resolveMulti(trace) | ||
return { resolved: resolved } | ||
} |
@@ -1,4 +0,2 @@ | ||
'use strict'; | ||
// no op function since we cannot resolve symbols in the browser (no access to .map file | ||
module.exports = function resolveSymbols(pid, trace) { return trace; } | ||
module.exports = function resolveSymbols(pid, trace) { return trace } |
@@ -1,15 +0,13 @@ | ||
'use strict'; | ||
var path = require('path') | ||
, fs = require('fs') | ||
, resolveSymbolsFromMap = require('./resolve-symbols-from-map') | ||
, mapFilesDir = '/tmp' | ||
var fs = require('fs') | ||
var resolveSymbolsFromMap = require('./resolve-symbols-from-map') | ||
var mapFilesDir = '/tmp' | ||
// only used on command line, so sync ops are ok | ||
exports = module.exports = | ||
exports = module.exports = | ||
/** | ||
* Tries to find a `perf-<pid>.map` file for the given `pid` in the `/tmp` dir. | ||
* If found it will use it's symbol information in order to resolve symbols in the given trace. | ||
* | ||
* | ||
* @name resolveSymbols | ||
@@ -23,15 +21,16 @@ * @function | ||
function resolveSymbols(pid, trace) { | ||
var file = path.join(mapFilesDir, 'perf-' + pid + '.map'); | ||
var file = path.join(mapFilesDir, 'perf-' + pid + '.map') | ||
if (!fs.existsSync(file)) | ||
return { | ||
if (!fs.existsSync(file)) { | ||
return { | ||
resolved: false | ||
, reason: 'Could not find "' + file + '". Did you run your process with --perf-basic-prof flag?' | ||
} | ||
} | ||
var stats = fs.statSync(file) | ||
if (!stats.size) | ||
return { | ||
if (!stats.size) { | ||
return { | ||
resolved: false | ||
, reason: | ||
, reason: | ||
'File "' + file + '" did you properly shut down your process?.\n' | ||
@@ -42,5 +41,6 @@ + 'Try either of the following to ensure the perf-<pid>.map file gets flushes:\n' | ||
} | ||
var map = fs.readFileSync(file, 'utf8'); | ||
return resolveSymbolsFromMap(map, trace); | ||
} | ||
var map = fs.readFileSync(file, 'utf8') | ||
return resolveSymbolsFromMap(map, trace) | ||
} |
@@ -1,10 +0,8 @@ | ||
'use strict'; | ||
exports.normalizeEmptyLines = function normalizeEmptyLines(trace) { | ||
// need *exactly* ONE empty line after last stack | ||
var l = trace.length - 1; | ||
while(l > 0 && trace[l].trim() === '') l--; | ||
trace.length = l + 2; | ||
trace[l + 1] = ''; | ||
return trace; | ||
var l = trace.length - 1 | ||
while (l > 0 && trace[l].trim() === '') l-- | ||
trace.length = l + 2 | ||
trace[l + 1] = '' | ||
return trace | ||
} | ||
@@ -15,4 +13,4 @@ | ||
// ignore empty lines and comments starting with # | ||
if (lines[i] && lines[i].length && lines[i][0] !== '#') return i; | ||
if (lines[i] && lines[i].length && lines[i][0] !== '#') return i | ||
} | ||
} |
{ | ||
"name": "cpuprofilify", | ||
"version": "0.4.0", | ||
"version": "1.0.0", | ||
"description": "Converts output of various profiling/sampling tools to the .cpuprofile format so it can be loaded into Chrome DevTools.", | ||
@@ -8,3 +8,3 @@ "main": "index.js", | ||
"docme": "docme README.md -- --configure .jsdocrc", | ||
"test": "tape test/*.js" | ||
"test": "tape test/*.js && standart" | ||
}, | ||
@@ -15,2 +15,9 @@ "bin": { | ||
}, | ||
"files": [ | ||
"index.js", | ||
"bin", | ||
"lib", | ||
"LICENSE", | ||
"README.md" | ||
], | ||
"browser": { | ||
@@ -28,3 +35,3 @@ "./lib/resolve-symbols.js": "./lib/resolve-symbols.browser.js" | ||
"npmlog": "~1.0.0", | ||
"resolve-jit-symbols": "~0.4.3", | ||
"resolve-jit-symbols": "~0.5.0", | ||
"trace-filter-internals": "^0.1.0", | ||
@@ -35,2 +42,3 @@ "xtend": "~4.0.0" | ||
"JSONSelect": "~0.4.0", | ||
"standart": "~6.1.0", | ||
"tape": "~3.4.0" | ||
@@ -37,0 +45,0 @@ }, |
@@ -34,6 +34,10 @@ # cpuprofilify [![build status](https://secure.travis-ci.org/thlorenz/cpuprofilify.png?branch=master)](http://travis-ci.org/thlorenz/cpuprofilify) | ||
- **`profile_1ms.d`**: DTrace script that samples your process, use either of the following to generate a trace | ||
- `sudo profile_1ms.d -c <command> | cpuprofilify > out.cpuprofile` | ||
- `sudo profile_1ms.d -c 'node --perf-basic-prof <app>' | cpuprofilify > out.cpuprofile` | ||
- `sudo profile_1ms.d -p <process id> | cpuprofilify > out.cpuprofile` | ||
- **`cpuprofilify`**: which will convert a *perf* or *DTrace* trace into a `.cpuprofile` importable into Chrome DevTools | ||
- `perf record -e cycles:u -g -- node --perf-basic-prof <app> && perf script | cpuprofilify > out.cpuprofile` | ||
Use the `perf record` and `perf script` commands on Linux to generate input to cpuprofilify and the provided | ||
`profile_1ms.d` script to do so on OSX via dtrace. | ||
## Example | ||
@@ -69,3 +73,3 @@ | ||
``` | ||
cat trace.txt | cpuprofilify <options> > my.cpuprofile | ||
cat trace.txt | cpuprofilify <options> > my.cpuprofile | ||
@@ -86,3 +90,3 @@ Converts the given trace taking according to the given opttions | ||
--type type of input `perf|dtrace|instruments`. If not supplied it will be detected. | ||
--type type of input `perf|dtrace`. If not supplied it will be detected. | ||
--help print this help | ||
@@ -92,3 +96,3 @@ | ||
Generate cpuprofile from DTrace data with default options | ||
Generate cpuprofile from DTrace data with default options | ||
using higher switchrate in order to deal with large amount of data being emitted | ||
@@ -103,3 +107,3 @@ | ||
Generate cpuprofile from DTrace data with default options filtering v8 gc events | ||
sudo profile_1ms.d -c <command> | cpuprofilify --nov8gc > out.cpuprofile | ||
@@ -210,3 +214,3 @@ ``` | ||
</td> | ||
<td class="description last"><p>type of input <code>perf|dtrace|instruments</code>. If not supplied it will be detected.</p></td> | ||
<td class="description last"><p>type of input <code>perf|dtrace</code>. If not supplied it will be detected.</p></td> | ||
</tr> | ||
@@ -213,0 +217,0 @@ <tr> |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
294
1
31902
3
17
427
1
+ Addedresolve-jit-symbols@0.5.0(transitive)
- Removedresolve-jit-symbols@0.4.3(transitive)
Updatedresolve-jit-symbols@~0.5.0