Commit 07eab906 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Improve filtering of top instance types in heap stats

Bug: v8:7266
Change-Id: Ifd3feedb0338fff9f442d6bb44c0dab5c1ac9fc6
R: mlippautz@chromium.orgA
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/943110Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51677}
parent 5b0a1eef
......@@ -42,8 +42,43 @@ found in the LICENSE file. -->
}
.boxDiv {
padding: 3px;
padding: 0px 5px 2px 0px;
float: left;
margin: 3px;
}
.percent100 {
background: linear-gradient(70deg, #9cf 100%, #e0edfe 100%)
}
.percent90 {
background: linear-gradient(70deg, #9cf 90%, #e0edfe 90%)
}
.percent80 {
background: linear-gradient(70deg, #9cf 80%, #e0edfe 80%)
}
.percent70 {
background: linear-gradient(70deg, #9cf 70%, #e0edfe 70%)
}
.percent60 {
background: linear-gradient(70deg, #9cf 60%, #e0edfe 60%)
}
.percent50 {
background: linear-gradient(70deg, #9cf 50%, #e0edfe 50%)
}
.percent40 {
background: linear-gradient(70deg, #9cf 40%, #e0edfe 40%)
}
.percent30 {
background: linear-gradient(70deg, #9cf 30%, #e0edfe 30%)
}
.percent20 {
background: linear-gradient(70deg, #9cf 20%, #e0edfe 20%)
}
.percent10 {
background: linear-gradient(70deg, #9cf 10%, #e0edfe 10%)
}
.percent0 {
background: linear-gradient(70deg, #9cf 0%, #e0edfe 0%)
}
.boxDiv > label {
......@@ -95,7 +130,12 @@ found in the LICENSE file. -->
</li>
<li>
<input id="category-filter" type="text" value="0" disabled="disabled" />KB
<button id="category-filter-btn" disabled="disabled">Filter categories with less memory</button>
<button id="category-filter-btn" disabled="disabled">
Filter categories with less memory
</button>
<button id="category-auto-filter-btn" disabled="disabled">
Show top 20 categories only
</button>
</li>
<li>
<button id="csv-export-btn" disabled="disabled">Export selection as CSV</button>
......
......@@ -25,6 +25,8 @@ class DetailsSelection extends HTMLElement {
.addEventListener('change', e => this.notifySelectionChanged(e));
this.$('#category-filter-btn')
.addEventListener('click', e => this.filterCurrentSeclection(e));
this.$('#category-auto-filter-btn')
.addEventListener('click', e => this.filterTop20Categories(e));
}
connectedCallback() {
......@@ -42,11 +44,14 @@ class DetailsSelection extends HTMLElement {
return this._data;
}
get selectedIsolate() {
return this._data[this.selection.isolate];
}
get selectedData() {
console.assert(this.data, 'invalid data');
console.assert(this.selection, 'invalid selection');
return this.data[this.selection.isolate]
.gcs[this.selection.gc][this.selection.data_set];
return this.selectedIsolate.gcs[this.selection.gc][this.selection.data_set];
}
buildCategory(name) {
......@@ -105,11 +110,11 @@ class DetailsSelection extends HTMLElement {
}
populateIsolateSelect() {
let entries = Object.entries(this.data);
let isolates = Object.entries(this.data);
// Sorty by peak heap memory consumption.
entries.sort((a, b) => b[1].peakMemory - a[1].peakMemory);
isolates.sort((a, b) => b[1].peakMemory - a[1].peakMemory);
this.populateSelect(
'#isolate-select', entries, (key, isolate) => isolate.getLabel());
'#isolate-select', isolates, (key, isolate) => isolate.getLabel());
}
resetUI(resetIsolateSelect) {
......@@ -118,9 +123,14 @@ class DetailsSelection extends HTMLElement {
removeAllChildren(this.datasetSelect);
removeAllChildren(this.gcSelect);
this.clearCategories();
this.$('#csv-export-btn').disabled = 'disabled';
this.$('#category-filter-btn').disabled = 'disabled';
this.$('#category-filter').disabled = 'disabled';
this.setButtonState('disabled');
}
setButtonState(disabled) {
this.$('#csv-export-btn').disabled = disabled;
this.$('#category-filter').disabled = disabled;
this.$('#category-filter-btn').disabled = disabled;
this.$('#category-auto-filter-btn').disabled = disabled;
}
handleIsolateChange(e) {
......@@ -131,12 +141,12 @@ class DetailsSelection extends HTMLElement {
}
this.resetUI(false);
this.populateSelect(
'#dataset-select',
this.data[this.selection.isolate].data_sets.entries(), null, 'live');
'#dataset-select', this.selectedIsolate.data_sets.entries(), null,
'live');
this.populateSelect(
'#gc-select',
Object.keys(this.data[this.selection.isolate].gcs)
.map(v => [v, this.data[this.selection.isolate].gcs[v].time]),
Object.keys(this.selectedIsolate.gcs)
.map(v => [v, this.selectedIsolate.gcs[v].time]),
time => time + 'ms');
this.populateCategories();
this.notifySelectionChanged();
......@@ -154,24 +164,39 @@ class DetailsSelection extends HTMLElement {
this.selection.data_set = this.datasetSelect.value;
this.selection.merge_categories = this.$('#merge-categories').checked;
this.selection.gc = this.gcSelect.value;
this.$('#csv-export-btn').disabled = false;
this.$('#category-filter-btn').disabled = false;
this.$('#category-filter').disabled = false;
this.setButtonState(false);
this.updatePercentagesInCategory();
this.dispatchEvent(new CustomEvent(
'change', {bubbles: true, composed: true, detail: this.selection}));
}
filterCurrentSeclection(e) {
const filter_value = this.$('#category-filter').value * KB;
if (filter_value === 0) return;
const minSize = this.$('#category-filter').value * KB;
this.filterCurrentSelectionWithThresold(minSize);
}
filterTop20Categories(e) {
// Limit to show top 20 categories only.
let minSize = 0;
let count = 0;
let sizes = this.selectedIsolate.instanceTypePeakMemory;
for (let key in sizes) {
if (count == 20) break;
minSize = sizes[key];
count++;
}
this.filterCurrentSelectionWithThresold(minSize);
}
filterCurrentSelectionWithThresold(minSize) {
if (minSize === 0) return;
this.selection.category_names.forEach((_, category) => {
for (let checkbox of this.shadowRoot.querySelectorAll(
'input[name=' + category + 'Checkbox]')) {
checkbox.checked =
this.selectedData.instance_type_data[checkbox.instance_type]
.overall > filter_value;
.overall > minSize;
}
});
this.notifySelectionChanged();
......@@ -250,8 +275,7 @@ class DetailsSelection extends HTMLElement {
categories[cat] = [];
}
for (let instance_type of this.data[this.selection.isolate]
.non_empty_instance_types) {
for (let instance_type of this.selectedIsolate.non_empty_instance_types) {
const category = this.categoryForType(instance_type);
categories[category].push(instance_type);
}
......@@ -283,6 +307,11 @@ class DetailsSelection extends HTMLElement {
createCheckBox(instance_type, category) {
const div = document.createElement('div');
div.classList.add('boxDiv');
let peakMemory =
this.selectedIsolate.getInstanceTypePeakMemory(instance_type);
let maxInstanceType = this.selectedIsolate.singleInstanceTypePeakMemory;
let percentRounded = Math.round(peakMemory / maxInstanceType * 10) * 10;
div.classList.add('percent' + percentRounded);
const input = document.createElement('input');
div.appendChild(input);
input.type = 'checkbox';
......@@ -301,9 +330,9 @@ class DetailsSelection extends HTMLElement {
exportCurrentSelection(e) {
const data = [];
const selected_data = this.data[this.selection.isolate]
.gcs[this.selection.gc][this.selection.data_set]
.instance_type_data;
const selected_data =
this.selectedIsolate.gcs[this.selection.gc][this.selection.data_set]
.instance_type_data;
Object.values(this.selection.categories).forEach(instance_types => {
instance_types.forEach(instance_type => {
data.push([instance_type, selected_data[instance_type].overall / KB]);
......
......@@ -16,10 +16,15 @@ class Isolate {
this.samples = {zone: {}};
this.data_sets = new Set();
this.peakMemory = 0;
// Maps instance_types to their max memory consumption over all gcs.
this.instanceTypePeakMemory = Object.create(null);
// Peak memory consumed by any single instance type.
this.singleInstanceTypePeakMemory = 0;
}
finalize() {
Object.values(this.gcs).forEach(gc => this.finalizeGC(gc));
this.sortInstanceTypePeakMemory();
}
getLabel() {
......@@ -31,8 +36,13 @@ class Isolate {
finalizeGC(gc_data) {
this.data_sets.forEach(key => this.finalizeDataSet(gc_data[key]));
if ('live' in gc_data) {
this.peakMemory = Math.max(this.peakMemory, gc_data['live'].overall);
if (!('live' in gc_data)) return;
let liveData = gc_data.live;
this.peakMemory = Math.max(this.peakMemory, liveData.overall);
let data = liveData.instance_type_data;
for (let name in data) {
let prev = this.instanceTypePeakMemory[name] || 0;
this.instanceTypePeakMemory[name] = Math.max(prev, data[name].overall);
}
}
......@@ -74,4 +84,21 @@ class Isolate {
`${type}: sum('${histogram}') > overall (${sum} > ${overall})`);
}
}
sortInstanceTypePeakMemory() {
let entries = Object.entries(this.instanceTypePeakMemory);
entries.sort((a, b) => {return b[1] - a[1]});
this.instanceTypePeakMemory = Object.create(null);
let max = 0;
for (let [key, value] of entries) {
this.instanceTypePeakMemory[key] = value;
max = Math.max(max, value);
}
this.singleInstanceTypePeakMemory = max;
}
getInstanceTypePeakMemory(type) {
if (!(type in this.instanceTypePeakMemory)) return 0;
return this.instanceTypePeakMemory[type];
}
}
......@@ -51,10 +51,10 @@ found in the LICENSE file. -->
@keyframes spin {
0% {
transform: rotate(0deg);
};
}
100% {
transform: rotate(360deg);
};
}
}
</style>
......
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