mirror of
https://github.com/jlfwong/speedscope.git
synced 2024-11-22 22:14:25 +03:00
73 lines
1.9 KiB
TypeScript
73 lines
1.9 KiB
TypeScript
import {Frame, CallTreeNode} from './profile'
|
|
import { Color } from './color'
|
|
|
|
import { lastOf } from './utils'
|
|
|
|
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: (value: number) => void
|
|
): void
|
|
|
|
getColorForFrame(f: Frame): Color
|
|
}
|
|
|
|
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 }
|
|
getColorForFrame(f: Frame) { return this.source.getColorForFrame(f) }
|
|
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 = (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)
|
|
}
|
|
} |