Commit da438d9e authored by Camillo Bruni's avatar Camillo Bruni Committed by V8 LUCI CQ

[tools][system-analyzer] Fix stack calculation

Traverse the sampled stack in the correct order. This results in several
order of magnitudes fewer flames rects.

- Fix flame rendering by having a fixed-width border
- Speed up flame rendering by setting shape-rendering to optimizeSpeed
- Fix rendering empty timelines

Bug: v8:10644, v8:11835
Change-Id: I5195d4d16a15c927ab25c7c111db69eeb0b0641a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2951728
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarPatrick Thier <pthier@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75084}
parent 13e95258
...@@ -204,6 +204,7 @@ export class TimelineTrackBase extends V8CustomElement { ...@@ -204,6 +204,7 @@ export class TimelineTrackBase extends V8CustomElement {
async _drawContent() { async _drawContent() {
await delay(5); await delay(5);
if (this._timeline.isEmpty()) return;
if (this.chunks?.length != this.nofChunks) { if (this.chunks?.length != this.nofChunks) {
this._chunks = this._chunks =
this._timeline.chunks(this.nofChunks, this._legend.filterPredicate); this._timeline.chunks(this.nofChunks, this._legend.filterPredicate);
......
...@@ -148,23 +148,6 @@ found in the LICENSE file. --> ...@@ -148,23 +148,6 @@ found in the LICENSE file. -->
flex: initial; flex: initial;
} }
.flame {
background-color: gray;
overflow: hidden;
height: 10px;
position: absolute;
font-size: 8px;
content-visibility: auto;
}
.flame.Opt{
background-color: red;
}
.flame.Baseline{
background-color: blue;
}
.flame.default {
background-color: black;
}
.txt { .txt {
font: 8px monospace; font: 8px monospace;
} }
...@@ -190,11 +173,19 @@ found in the LICENSE file. --> ...@@ -190,11 +173,19 @@ found in the LICENSE file. -->
dominant-baseline: hanging; dominant-baseline: hanging;
font-size: 9px; font-size: 9px;
} }
.flame {
stroke: var(--background-color);
stroke-width: 1;
vector-effect: non-scaling-stroke;
}
.flameSelected { .flameSelected {
fill: none; fill: none;
stroke: var(--on-background-color); stroke: var(--on-background-color);
stroke-width: 1;
vector-effect: non-scaling-stroke;
} }
#scalableContent { svg {
shape-rendering: optimizeSpeed;
} }
</style> </style>
......
...@@ -15,6 +15,7 @@ class Flame { ...@@ -15,6 +15,7 @@ class Flame {
this.entry = entry; this.entry = entry;
this.depth = depth; this.depth = depth;
this.id = id; this.id = id;
this.duration = -1;
} }
stop(time) { stop(time) {
this.duration = time - this.time this.duration = time - this.time
...@@ -62,37 +63,41 @@ DOM.defineCustomElement('view/timeline/timeline-track', 'timeline-track-tick', ...@@ -62,37 +63,41 @@ DOM.defineCustomElement('view/timeline/timeline-track', 'timeline-track-tick',
_updateFlames() { _updateFlames() {
const tmpFlames = []; const tmpFlames = [];
const stack = []; // flameStack = [bottom, ..., top];
const flameStack = [];
const ticks = this._timeline.values; const ticks = this._timeline.values;
let maxDepth = 0; let maxDepth = 0;
for (let tickIndex = 0; tickIndex < ticks.length; tickIndex++) { for (let tickIndex = 0; tickIndex < ticks.length; tickIndex++) {
const tick = ticks[tickIndex]; const tick = ticks[tickIndex];
maxDepth = Math.max(maxDepth, tick.stack.length); maxDepth = Math.max(maxDepth, tick.stack.length);
for (let stackIndex = 0; stackIndex < tick.stack.length; stackIndex++) { // tick.stack = [top, .... , bottom];
for (let stackIndex = tick.stack.length - 1; stackIndex >= 0;
stackIndex--) {
const entry = tick.stack[stackIndex]; const entry = tick.stack[stackIndex];
if (stack.length <= stackIndex) { const flameStackIndex = tick.stack.length - stackIndex - 1;
const newFlame = if (flameStackIndex < flameStack.length) {
new Flame(tick.time, entry, stackIndex, tmpFlames.length); if (flameStack[flameStackIndex].entry === entry) continue;
tmpFlames.push(newFlame); for (let k = flameStackIndex; k < flameStack.length; k++) {
stack.push(newFlame); flameStack[k].stop(tick.time);
} else {
if (stack[stackIndex].entry !== entry) {
for (let k = stackIndex; k < stack.length; k++) {
stack[k].stop(tick.time);
}
stack.length = stackIndex;
const replacementFlame =
new Flame(tick.time, entry, stackIndex, tmpFlames.length);
tmpFlames.push(replacementFlame);
stack[stackIndex] = replacementFlame;
} }
flameStack.length = flameStackIndex;
} }
const newFlame =
new Flame(tick.time, entry, flameStack.length, tmpFlames.length);
tmpFlames.push(newFlame);
flameStack.push(newFlame);
}
if (tick.stack.length < flameStack.length) {
for (let k = tick.stack.length; k < flameStack.length; k++) {
flameStack[k].stop(tick.time);
}
flameStack.length = tick.stack.length;
} }
} }
const lastTime = ticks[ticks.length - 1].time; const lastTime = ticks[ticks.length - 1].time;
for (let stackIndex = 0; stackIndex < stack.length; stackIndex++) { for (let k = 0; k < flameStack.length; k++) {
stack[stackIndex].stop(lastTime); flameStack[k].stop(lastTime);
} }
this._flames = new Timeline(Flame, tmpFlames); this._flames = new Timeline(Flame, tmpFlames);
this._annotations.flames = this._flames; this._annotations.flames = this._flames;
...@@ -134,12 +139,11 @@ DOM.defineCustomElement('view/timeline/timeline-track', 'timeline-track-tick', ...@@ -134,12 +139,11 @@ DOM.defineCustomElement('view/timeline/timeline-track', 'timeline-track-tick',
drawFlame(flame, outline = false) { drawFlame(flame, outline = false) {
const x = this.timeToPosition(flame.time); const x = this.timeToPosition(flame.time);
const y = (flame.depth + 1) * kFlameHeight; const y = (flame.depth + 1) * kFlameHeight;
let width = (flame.duration * this._timeToPixel) * 0.9; let width = flame.duration * this._timeToPixel;
let height = kFlameHeight - 1;
if (outline) { if (outline) {
return `<rect x=${x} y=${y} width=${width} height=${ return `<rect x=${x} y=${y} width=${width} height=${
height} class=flameSelected />`; kFlameHeight} class=flameSelected />`;
} }
let type = 'native'; let type = 'native';
...@@ -147,8 +151,8 @@ DOM.defineCustomElement('view/timeline/timeline-track', 'timeline-track-tick', ...@@ -147,8 +151,8 @@ DOM.defineCustomElement('view/timeline/timeline-track', 'timeline-track-tick',
type = Profile.getKindFromState(flame.entry.state); type = Profile.getKindFromState(flame.entry.state);
} }
const color = this._legend.colorForType(type); const color = this._legend.colorForType(type);
return `<rect x=${x} y=${y} width=${width} height=${height} fill=${ return `<rect x=${x} y=${y} width=${width} height=${kFlameHeight} fill=${
color} data-id=${flame.id} />`; color} data-id=${flame.id} class=flame />`;
} }
drawFlameText(flame) { drawFlameText(flame) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment