blob: 3ade95e83047de64c1ad170fbac7a1aa7dabac0a [file] [log] [blame]
// 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';
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 CustomEvent(
'change', {bubbles: true, composed: true, detail: 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 CustomEvent(
'change', {bubbles: true, composed: true,
detail: 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);
}
});