Files
SpeedScope/flamechart.ts
Jamie Wong d659eb0159 Add a hotkey to flatten recursion (#68)
This makes the left-heavy view much more useful since recursive calls are all collapsed together.

Press `r` to activate

Fixes #37
2018-06-21 13:56:58 -07:00

85 lines
2.1 KiB
TypeScript

import {Frame, CallTreeNode} from './profile'
import {lastOf} from './utils'
export interface FlamechartFrame {
node: CallTreeNode
start: number
end: number
parent: FlamechartFrame | null
children: FlamechartFrame[]
}
type StackLayer = FlamechartFrame[]
interface FlamechartDataSource {
getTotalWeight(): number
formatValue(v: number): string
forEachCall(
openFrame: (node: CallTreeNode, value: number) => void,
closeFrame: (node: CallTreeNode, value: number) => void,
): void
getColorBucketForFrame(f: Frame): number
}
export class Flamechart {
// Bottom to top
private layers: StackLayer[] = []
private totalWeight: number = 0
private minFrameWidth: number = 1
getTotalWeight() {
return this.totalWeight
}
getLayers() {
return this.layers
}
getColorBucketForFrame(frame: Frame) {
return this.source.getColorBucketForFrame(frame)
}
getMinFrameWidth() {
return this.minFrameWidth
}
formatValue(v: number) {
return this.source.formatValue(v)
}
constructor(private source: FlamechartDataSource) {
const stack: FlamechartFrame[] = []
const openFrame = (node: CallTreeNode, value: number) => {
const parent = lastOf(stack)
const frame: FlamechartFrame = {
node,
parent,
children: [],
start: value,
end: value,
}
if (parent) {
parent.children.push(frame)
}
stack.push(frame)
}
this.minFrameWidth = Infinity
const closeFrame = (node: CallTreeNode, value: number) => {
console.assert(stack.length > 0)
const stackTop = stack.pop()!
stackTop.end = value
if (stackTop.end - stackTop.start === 0) return
const layerIndex = stack.length
while (this.layers.length <= layerIndex) this.layers.push([])
this.layers[layerIndex].push(stackTop)
this.minFrameWidth = Math.min(this.minFrameWidth, stackTop.end - stackTop.start)
}
this.totalWeight = source.getTotalWeight()
source.forEachCall(openFrame, closeFrame)
if (!isFinite(this.minFrameWidth)) this.minFrameWidth = 1
}
}