0x/stack-convert.js
2016-03-02 18:00:44 +00:00

129 lines
2.6 KiB
JavaScript

var eos = require('end-of-stream')
var through = require('through2')
var profLabel = process.platform === 'darwin' ? 'profile-1ms' : 'cpu-clock'
var debug = require('debug')('0x:stack-convert')
function Node (name) {
this.name = name
this.value = 0
this.top = 0
this.children = {}
}
Node.prototype.add = function (frames, value, topper) {
this.value += value
if (frames && frames.length > 0) {
var head = frames[0]
var child = this.children[head]
if (!child) {
child = new Node(head)
this.children[head] = child
}
if (head === topper) child.top += 1
frames.splice(0, 1)
child.add(frames, value, topper)
}
}
Node.prototype.serialize = function () {
var res = {
name: this.name,
value: this.value,
top: this.top
}
var children = []
for (var key in this.children) {
children.push(this.children[key].serialize())
}
if (children.length > 0) res.children = children
return res
}
function Profile () {
this.samples = new Node('root')
this.stack = null
this.name = profLabel
}
Profile.prototype.openStack = function (name) {
this.stack = []
this.name = name
}
Profile.prototype.addFrame = function (frame) {
if (!this.stack) this.stack = []
frame = frame.replace(/^\s+/, '').replace(/\s+$/, '')
if (!frame.length) return
this.stack.unshift(
frame
.replace(/^\w+ /, '')
.replace(/ \(\S+\)$/, '')
.replace(/(..)[(<].*/, '$1')
)
}
Profile.prototype.closeStack = function () {
if (this.stack) {
this.stack.unshift(this.name)
this.samples.add(this.stack, 1, this.stack[this.stack.length - 1])
}
this.stack = []
this.name = profLabel
}
function stream () {
var stackOpenRx = /(.+):(.+): ?$/
var stackCloseRx = /^$/g
var commentRx = /^#/g
var profile = new Profile()
var s = through(function (line, enc, cb) {
if (commentRx.exec(line)) return cb()
var matches = stackOpenRx.exec(line)
if (matches) {
profile.openStack(matches[2].trim())
return cb()
}
matches = stackCloseRx.exec(line)
if (matches) {
profile.closeStack()
return cb()
}
if (!/\[unknown\]/.test(line)) {
profile.addFrame(line + '')
}
cb()
})
s.profile = profile
return s
}
module.exports = function convert (cb) {
var s = stream()
s.on('pipe', function (src) {
eos(src, function () {
var samples = s.profile.samples
samples = samples.children['profile-1ms'] || samples.children['cpu-clock'] || samples
samples.name = ''
debug('serializing samples')
samples = samples.serialize()
debug('samples serialized')
cb(null, samples)
})
})
return s
}