v8/tools/system-analyzer/stats-panel.mjs
Zeynep Cankara 393e434479 [tools][system-analyzer] Unify CustomEvents
This CL unifies the custom events by creating
classes specialised based on the event type.
Multiple entry selection causes panels to
emit 'showentries' event. Single entry selection
causes panels to emit 'showentrydetail' event.
The events are received by the controller App class
and updates the view of the panels and state of the app.

Bug: v8:10644

Change-Id: Ibe26223459ba605c6d6d3f0025bf3a556dfb0578
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2335188
Commit-Queue: Zeynep Cankara <zcankara@google.com>
Reviewed-by: Sathya Gunasekaran  <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69286}
2020-08-07 10:06:47 +00:00

125 lines
3.9 KiB
JavaScript

// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {V8CustomElement, defineCustomElement} from './helper.mjs';
import {SelectionEvent} from './events.mjs';
defineCustomElement('stats-panel', (templateText) =>
class StatsPanel extends V8CustomElement {
#timeline;
#transitions;
constructor() {
super(templateText);
}
get stats() {
return this.$('#stats');
}
set timeline(value){
//TODO(zcankara) Trigger update
this.#timeline = value;
}
get timeline(){
return this.#timeline;
}
set transitions(value){
this.#transitions = value;
}
get transitions(){
return this.#transitions;
}
filterUniqueTransitions(filter) {
// Returns a list of Maps whose parent is not in the list.
return this.timeline.filter(map => {
if (filter(map) === false) return false;
let parent = map.parent();
if (parent === undefined) return true;
return filter(parent) === false;
});
}
update() {
this.removeAllChildren(this.stats);
this.updateGeneralStats();
this.updateNamedTransitionsStats();
}
updateGeneralStats() {
console.assert(this.#timeline !== undefined, "Timeline not set yet!");
let pairs = [
['Total', null, e => true],
['Transitions', 'primary', e => e.edge && e.edge.isTransition()],
['Fast to Slow', 'violet', e => e.edge && e.edge.isFastToSlow()],
['Slow to Fast', 'orange', e => e.edge && e.edge.isSlowToFast()],
['Initial Map', 'yellow', e => e.edge && e.edge.isInitial()],
[
'Replace Descriptors', 'red',
e => e.edge && e.edge.isReplaceDescriptors()
],
['Copy as Prototype', 'red', e => e.edge && e.edge.isCopyAsPrototype()],
[
'Optimize as Prototype', null,
e => e.edge && e.edge.isOptimizeAsPrototype()
],
['Deprecated', null, e => e.isDeprecated()],
['Bootstrapped', 'green', e => e.isBootstrapped()],
];
let text = '';
let tableNode = this.table('transitionType');
tableNode.innerHTML =
'<thead><tr><td>Color</td><td>Type</td><td>Count</td><td>Percent</td></tr></thead>';
let name, filter;
let total = this.timeline.size();
pairs.forEach(([name, color, filter]) => {
let row = this.tr();
if (color !== null) {
row.appendChild(this.td(this.div(['colorbox', color])));
} else {
row.appendChild(this.td(''));
}
row.onclick = (e) => {
// lazily compute the stats
let node = e.target.parentNode;
if (node.maps == undefined) {
node.maps = this.filterUniqueTransitions(filter);
}
this.dispatchEvent(new SelectionEvent(node.maps));
};
row.appendChild(this.td(name));
let count = this.timeline.count(filter);
row.appendChild(this.td(count));
let percent = Math.round(count / total * 1000) / 10;
row.appendChild(this.td(percent.toFixed(1) + '%'));
tableNode.appendChild(row);
});
this.stats.appendChild(tableNode);
}
updateNamedTransitionsStats() {
let tableNode = this.table('transitionTable');
let nameMapPairs = Array.from(this.transitions.entries());
tableNode.innerHTML =
'<thead><tr><td>Propery Name</td><td>#</td></tr></thead>';
nameMapPairs.sort((a, b) => b[1].length - a[1].length).forEach(([
name, maps
]) => {
let row = this.tr();
row.maps = maps;
row.addEventListener(
'click',
e => this.dispatchEvent(
new SelectionEvent(e.target.parentNode.maps.map(map => map.to))));
row.appendChild(this.td(name));
row.appendChild(this.td(maps.length));
tableNode.appendChild(row);
});
this.stats.appendChild(tableNode);
}
});