mirror of
https://github.com/davidmarkclements/0x.git
synced 2026-01-18 14:38:23 +00:00
129 lines
2.6 KiB
JavaScript
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
|
|
}
|