diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-03-05 17:34:47 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-03-06 10:04:14 +0000 |
commit | eaf1da4d961fbbda9455f9af3b23d1af777f43fa (patch) | |
tree | 95970599ecee31c4f7f940bc97ac98c61a3d0cad /chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html | |
parent | 38a9a29f4f9436cace7f0e7abf9c586057df8a4e (diff) |
BASELINE: Update Chromium to 73.0.3683.64
Change-Id: I76517dc277ba4e16bfd7e098fda3d079656b3b9f
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html')
-rw-r--r-- | chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html | 728 |
1 files changed, 728 insertions, 0 deletions
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html new file mode 100644 index 00000000000..bc3247d9289 --- /dev/null +++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html @@ -0,0 +1,728 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2016 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<link rel="import" href="/tracing/extras/v8/v8_gc_stats_thread_slice.html"> +<link rel="import" href="/tracing/ui/base/table.html"> + +<dom-module id='tr-ui-e-v8-gc-objects-stats-table'> + <template> + <style> + tr-ui-b-table { + flex: 0 0 auto; + align-self: stretch; + margin-top: 1em; + font-size: 12px; + } + .diff { + display: inline-block; + margin-top: 1em; + margin-left: 0.8em; + } + </style> + <div class="diff" id="diffOption"> + Diff + </div> + <tr-ui-b-table id="diffTable"></tr-ui-b-table> + <tr-ui-b-table id="table"></tr-ui-b-table> + </template> +</dom-module> +<script> +'use strict'; + +tr.exportTo('tr.ui.e.v8', function() { + // Instance types that should not be part of the overview as they are either + // double-attributed (e.g. also part of some other instance type) or do not + // make any sense in memory profiling. + const IGNORED_ENTRIES = { + // Ignore code aging entries as they are already accounted in their + // respective code instance types. + match: full => full.startsWith('*CODE_AGE_') + }; + + // Groups are matched on a first-matched basis, i.e., once a group matches we + // are done with an entry. + // Requires properties: + // - match(full): Return true iff |full| should be part of the group and + // false otherwise. + // - keyToName(key): Returns the human readable name for |key|. + // - nameToKey(name): Returns the key for |name|. + // Optional properties: + // - realEntry: A string representing the actual entry in the trace. If this + // entry is present an additional entry UNKNOWN will be created holding all + // the unaccounted data. + const INSTANCE_TYPE_GROUPS = { + FIXED_ARRAY_TYPE: { + match: full => full.startsWith('*FIXED_ARRAY_'), + realEntry: 'FIXED_ARRAY_TYPE', + keyToName: key => key.slice('*FIXED_ARRAY_'.length) + .slice(0, -('_SUB_TYPE'.length)), + nameToKey: name => '*FIXED_ARRAY_' + name + '_SUB_TYPE' + }, + CODE_TYPE: { + match: full => full.startsWith('*CODE_'), + realEntry: 'CODE_TYPE', + keyToName: key => key.slice('*CODE_'.length), + nameToKey: name => '*CODE_' + name + }, + JS_OBJECTS: { + match: full => full.startsWith('JS_'), + keyToName: key => key, + nameToKey: name => name + }, + Strings: { + match: full => full.endsWith('STRING_TYPE'), + keyToName: key => key, + nameToKey: name => name + } + }; + + const DIFF_COLOR = { + GREEN: '#64DD17', + RED: '#D50000' + }; + + function computePercentage(valueA, valueB) { + if (valueA === 0) return 0; + return valueA / valueB * 100; + } + + class DiffEntry { + constructor(originalEntry, diffEntry) { + this.originalEntry_ = originalEntry; + this.diffEntry_ = diffEntry; + } + get title() { + return this.diffEntry_.title; + } + get overall() { + return this.diffEntry_.overall; + } + get overAllocated() { + return this.diffEntry_.overAllocated; + } + get count() { + return this.diffEntry_.count; + } + get overallPercent() { + return this.diffEntry_.overallPercent; + } + get overAllocatedPercent() { + return this.diffEntry_.overAllocatedPercent; + } + get origin() { + return this.originalEntry_; + } + get diff() { + return this.diffEntry_; + } + get subRows() { + return this.diffEntry_.subRows; + } + } + + class Entry { + constructor(title, count, overall, overAllocated, histogram, + overAllocatedHistogram) { + this.title_ = title; + this.overall_ = overall; + this.count_ = count; + this.overAllocated_ = overAllocated; + this.histogram_ = histogram; + this.overAllocatedHistogram_ = overAllocatedHistogram; + this.bucketSize_ = this.histogram_.length; + this.overallPercent_ = 100; + this.overAllocatedPercent_ = 100; + } + + get title() { + return this.title_; + } + + get overall() { + return this.overall_; + } + + get count() { + return this.count_; + } + + get overAllocated() { + return this.overAllocated_; + } + + get histogram() { + return this.histogram_; + } + + get overAllocatedHistogram() { + return this.overAllocatedHistogram_; + } + + get bucketSize() { + return this.bucketSize_; + } + + get overallPercent() { + return this.overallPercent_; + } + + set overallPercent(value) { + this.overallPercent_ = value; + } + + get overAllocatedPercent() { + return this.overAllocatedPercent_; + } + + set overAllocatedPercent(value) { + this.overAllocatedPercent_ = value; + } + + setFromObject(obj) { + this.count_ = obj.count; + // Calculate memory in KB. + this.overall_ = obj.overall / 1024; + this.overAllocated_ = obj.over_allocated / 1024; + this.histogram_ = obj.histogram; + this.overAllocatedHistogram_ = obj.over_allocated_histogram; + } + + diff(other) { + const entry = new Entry(this.title_, other.count_ - this.count, + other.overall_ - this.overall, + other.overAllocated_ - this.overAllocated, [], []); + entry.overallPercent = computePercentage(entry.overall, this.overall); + entry.overAllocatedPercent = computePercentage(entry.overAllocated, + this.overAllocated); + return new DiffEntry(this, entry); + } + } + + class GroupedEntry extends Entry { + constructor(title, count, overall, overAllocated, histogram, + overAllocatedHistogram) { + super(title, count, overall, overAllocated, histogram, + overAllocatedHistogram); + this.histogram_.fill(0); + this.overAllocatedHistogram_.fill(0); + this.entries_ = new Map(); + } + + get title() { + return this.title_; + } + + set title(value) { + this.title_ = value; + } + + get subRows() { + return Array.from(this.entries_.values()); + } + + getEntryFromTitle(title) { + return this.entries_.get(title); + } + + add(entry) { + this.count_ += entry.count; + this.overall_ += entry.overall; + this.overAllocated_ += entry.overAllocated; + if (this.bucketSize_ === entry.bucketSize) { + for (let i = 0; i < this.bucketSize_; ++i) { + this.histogram_[i] += entry.histogram[i]; + this.overAllocatedHistogram_[i] += entry.overAllocatedHistogram[i]; + } + } + this.entries_.set(entry.title, entry); + } + + accumulateUnknown(title) { + let unknownCount = this.count_; + let unknownOverall = this.overall_; + let unknownOverAllocated = this.overAllocated_; + const unknownHistogram = tr.b.deepCopy(this.histogram_); + const unknownOverAllocatedHistogram = + tr.b.deepCopy(this.overAllocatedHistogram_); + for (const entry of this.entries_.values()) { + unknownCount -= entry.count; + unknownOverall -= entry.overall; + unknownOverAllocated -= entry.overAllocated; + for (let i = 0; i < this.bucketSize_; ++i) { + unknownHistogram[i] -= entry.histogram[i]; + unknownOverAllocatedHistogram[i] -= entry.overAllocatedHistogram[i]; + } + } + unknownOverAllocated = + unknownOverAllocated < 0 ? 0 : unknownOverAllocated; + this.entries_.set(title, new Entry(title, unknownCount, unknownOverall, + unknownOverAllocated, unknownHistogram, + unknownOverAllocatedHistogram)); + } + + calculatePercentage() { + for (const entry of this.entries_.values()) { + entry.overallPercent = computePercentage(entry.overall, this.overall_); + entry.overAllocatedPercent = + computePercentage(entry.overAllocated, this.overAllocated_); + + if (entry instanceof GroupedEntry) entry.calculatePercentage(); + } + } + + diff(other) { + let newTitle = ''; + if (this.title_.startsWith('Isolate')) { + newTitle = 'Total'; + } else { + newTitle = this.title_; + } + const result = new GroupedEntry(newTitle, 0, 0, 0, [], []); + for (const entry of this.entries_) { + const otherEntry = other.getEntryFromTitle(entry[0]); + if (otherEntry === undefined) continue; + result.add(entry[1].diff(otherEntry)); + } + result.overallPercent = computePercentage(result.overall, this.overall); + result.overAllocatedPercent = computePercentage(result.overAllocated, + this.overAllocated); + return new DiffEntry(this, result); + } + } + + function createSelector(targetEl, defaultValue, items, callback) { + const selectorEl = document.createElement('select'); + selectorEl.addEventListener('change', callback.bind(targetEl)); + const defaultOptionEl = document.createElement('option'); + for (let i = 0; i < items.length; i++) { + const item = items[i]; + const optionEl = document.createElement('option'); + Polymer.dom(optionEl).textContent = item.label; + optionEl.targetPropertyValue = item.value; + optionEl.item = item; + Polymer.dom(selectorEl).appendChild(optionEl); + } + selectorEl.__defineGetter__('selectedValue', function(v) { + if (selectorEl.children[selectorEl.selectedIndex] === undefined) { + return undefined; + } + return selectorEl.children[selectorEl.selectedIndex].targetPropertyValue; + }); + selectorEl.__defineGetter__('selectedItem', function(v) { + if (selectorEl.children[selectorEl.selectedIndex] === undefined) { + return undefined; + } + return selectorEl.children[selectorEl.selectedIndex].item; + }); + selectorEl.__defineSetter__('selectedValue', function(v) { + for (let i = 0; i < selectorEl.children.length; i++) { + const value = selectorEl.children[i].targetPropertyValue; + if (value === v) { + const changed = selectorEl.selectedIndex !== i; + if (changed) { + selectorEl.selectedIndex = i; + callback(); + } + return; + } + } + throw new Error('Not a valid value'); + }); + selectorEl.selectedIndex = -1; + + return selectorEl; + } + + function plusMinus(value, toFixed = 3) { + return (value > 0 ? '+' : '') + value.toFixed(toFixed); + } + + function addArrow(value) { + if (value === 0) return value; + if (value === Number.NEGATIVE_INFINITY) return '\u2193\u221E'; + if (value === Number.POSITIVE_INFINITY) return '\u2191\u221E'; + return (value > 0 ? '\u2191' : '\u2193') + Math.abs(value.toFixed(3)); + } + + Polymer({ + is: 'tr-ui-e-v8-gc-objects-stats-table', + + ready() { + this.$.diffOption.style.display = 'none'; + this.isolateEntries_ = []; + this.selector1_ = undefined; + this.selector2_ = undefined; + }, + + constructDiffTable_(table) { + this.$.diffTable.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW; + this.$.diffTable.tableColumns = [ + { + title: 'Component', + value(row) { + const typeEl = document.createElement('span'); + typeEl.innerText = row.title; + return typeEl; + }, + showExpandButtons: true + }, + { + title: 'Overall Memory(KB)', + value(row) { + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = row.origin.overall.toFixed(3); + return spanEl; + }, + cmp(a, b) { + return a.origin.overall - b.origin.overall; + } + }, + { + title: 'diff(KB)', + value(row) { + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = plusMinus(row.overall); + if (row.overall > 0) { + spanEl.style.color = DIFF_COLOR.RED; + } else if (row.overall < 0) { + spanEl.style.color = DIFF_COLOR.GREEN; + } + return spanEl; + }, + cmp(a, b) { + return a.overall - b.overall; + } + }, + { + title: 'diff(%)', + value(row) { + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = addArrow(row.overallPercent); + if (row.overall > 0) { + spanEl.style.color = DIFF_COLOR.RED; + } else if (row.overall < 0) { + spanEl.style.color = DIFF_COLOR.GREEN; + } + return spanEl; + }, + cmp(a, b) { + return a.overall - b.overall; + } + }, + { + title: 'Over Allocated Memory(KB)', + value(row) { + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = row.origin.overAllocated.toFixed(3); + return spanEl; + }, + cmp(a, b) { + return a.origin.overAllocated - b.origin.overAllocated; + } + }, + { + title: 'diff(KB)', + value(row) { + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = plusMinus(row.overAllocated); + if (row.overAllocated > 0) { + spanEl.style.color = DIFF_COLOR.RED; + } else if (row.overAllocated < 0) { + spanEl.style.color = DIFF_COLOR.GREEN; + } + return spanEl; + }, + cmp(a, b) { + return a.overAllocated - b.overAllocated; + } + }, + { + title: 'diff(%)', + value(row) { + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = addArrow(row.overAllocatedPercent); + if (row.overAllocated > 0) { + spanEl.style.color = DIFF_COLOR.RED; + } else if (row.overAllocated < 0) { + spanEl.style.color = DIFF_COLOR.GREEN; + } + return spanEl; + }, + cmp(a, b) { + return a.overAllocated - b.overAllocated; + } + }, + { + title: 'Count', + value(row) { + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = row.origin.count; + return spanEl; + }, + cmp(a, b) { + return a.origin.count - b.origin.count; + } + }, + { + title: 'diff', + value(row) { + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = plusMinus(row.count, 0); + if (row.count > 0) { + spanEl.style.color = DIFF_COLOR.RED; + } else if (row.count < 0) { + spanEl.style.color = DIFF_COLOR.GREEN; + } + return spanEl; + }, + cmp(a, b) { + return a.count - b.count; + } + }, + ]; + }, + + buildOptions_() { + const items = []; + for (const isolateEntry of this.isolateEntries_) { + items.push({ + label: isolateEntry.title, + value: isolateEntry + }); + } + this.$.diffOption.style.display = 'inline-block'; + this.selector1_ = createSelector( + this, '', items, this.diffOptionChanged_); + Polymer.dom(this.$.diffOption).appendChild(this.selector1_); + const spanEl = tr.ui.b.createSpan(); + spanEl.innerText = ' VS '; + Polymer.dom(this.$.diffOption).appendChild(spanEl); + this.selector2_ = createSelector( + this, '', items, this.diffOptionChanged_); + Polymer.dom(this.$.diffOption).appendChild(this.selector2_); + }, + + diffOptionChanged_() { + const isolateEntry1 = this.selector1_.selectedValue; + const isolateEntry2 = this.selector2_.selectedValue; + if (isolateEntry1 === undefined || isolateEntry2 === undefined) { + return; + } + if (isolateEntry1 === isolateEntry2) { + this.$.diffTable.tableRows = []; + this.$.diffTable.rebuild(); + return; + } + this.$.diffTable.tableRows = [isolateEntry1.diff(isolateEntry2)]; + this.$.diffTable.rebuild(); + }, + + constructTable_() { + this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW; + this.$.table.tableColumns = [ + { + title: 'Component', + value(row) { + const typeEl = document.createElement('span'); + typeEl.innerText = row.title; + return typeEl; + }, + showExpandButtons: true + }, + { + title: 'Overall Memory (KB)', + value(row) { + const typeEl = document.createElement('span'); + typeEl.innerText = row.overall.toFixed(3); + return typeEl; + }, + cmp(a, b) { + return a.overall - b.overall; + } + }, + { + title: 'Over Allocated Memory (KB)', + value(row) { + const typeEl = document.createElement('span'); + typeEl.innerText = row.overAllocated.toFixed(3); + return typeEl; + }, + cmp(a, b) { + return a.overAllocated - b.overAllocated; + } + }, + { + title: 'Overall Count', + value(row) { + const typeEl = document.createElement('span'); + typeEl.innerText = row.count; + return typeEl; + }, + cmp(a, b) { + return a.count - b.count; + } + }, + { + title: 'Overall Memory Percent', + value(row) { + const typeEl = document.createElement('span'); + typeEl.innerText = row.overallPercent.toFixed(3) + '%'; + return typeEl; + }, + cmp(a, b) { + return a.overall - b.overall; + } + }, + { + title: 'Overall Allocated Memory Percent', + value(row) { + const typeEl = document.createElement('span'); + typeEl.innerText = row.overAllocatedPercent.toFixed(3) + '%'; + return typeEl; + }, + cmp(a, b) { + return a.overAllocated - b.overAllocated; + } + } + ]; + + this.$.table.sortColumnIndex = 1; + this.$.table.sortDescending = true; + }, + + buildSubEntry_(objects, groupEntry, keyToName) { + const typeGroup = INSTANCE_TYPE_GROUPS[groupEntry.title]; + for (const instanceType of typeGroup) { + const e = objects[instanceType]; + if (e === undefined) continue; + delete objects[instanceType]; + let title = instanceType; + if (keyToName !== undefined) title = keyToName(title); + // Represent memery in KB unit. + groupEntry.add(new Entry(title, e.count, e.overall / 1024, + e.over_allocated / 1024, e.histogram, + e.over_allocated_histogram)); + } + }, + + buildUnGroupedEntries_(objects, objectEntry, bucketSize) { + for (const title of Object.getOwnPropertyNames(objects)) { + const obj = objects[title]; + const groupedEntry = new GroupedEntry(title, 0, 0, 0, + new Array(bucketSize), + new Array(bucketSize)); + groupedEntry.setFromObject(obj); + objectEntry.add(groupedEntry); + } + }, + + createGroupEntries_(groupEntries, objects, bucketSize) { + for (const groupName of Object.getOwnPropertyNames( + INSTANCE_TYPE_GROUPS)) { + const groupEntry = new GroupedEntry(groupName, 0, 0, 0, + new Array(bucketSize), + new Array(bucketSize)); + if (INSTANCE_TYPE_GROUPS[groupName].realEntry !== undefined) { + groupEntry.savedRealEntry = + objects[INSTANCE_TYPE_GROUPS[groupName].realEntry]; + delete objects[INSTANCE_TYPE_GROUPS[groupName].realEntry]; + } + groupEntries[groupName] = groupEntry; + } + }, + + buildGroupEntries_(groupEntries, objectEntry) { + for (const groupName of Object.getOwnPropertyNames(groupEntries)) { + const groupEntry = groupEntries[groupName]; + if (groupEntry.savedRealEntry !== undefined) { + groupEntry.setFromObject(groupEntry.savedRealEntry); + groupEntry.accumulateUnknown('UNKNOWN'); + delete groupEntry.savedRealEntry; + } + objectEntry.add(groupEntry); + } + }, + + buildSubEntriesForGroups_(groupEntries, objects) { + for (const instanceType of Object.getOwnPropertyNames(objects)) { + if (IGNORED_ENTRIES.match(instanceType)) { + delete objects[instanceType]; + continue; + } + const e = objects[instanceType]; + for (const name of Object.getOwnPropertyNames(INSTANCE_TYPE_GROUPS)) { + const group = INSTANCE_TYPE_GROUPS[name]; + if (group.match(instanceType)) { + groupEntries[name].add(new Entry( + group.keyToName(instanceType), e.count, e.overall / 1024, + e.over_allocated / 1024, e.histogram, + e.over_allocated_histogram)); + delete objects[instanceType]; + } + } + } + }, + + build_(objects, objectEntry, bucketSize) { + delete objects.END; + const groupEntries = {}; + this.createGroupEntries_(groupEntries, objects, bucketSize); + this.buildSubEntriesForGroups_(groupEntries, objects); + this.buildGroupEntries_(groupEntries, objectEntry); + this.buildUnGroupedEntries_(objects, objectEntry, bucketSize); + }, + + set selection(slices) { + slices.sortEvents(function(a, b) { + return b.start - a.start; + }); + const previous = undefined; + for (const slice of slices) { + if (!slice instanceof tr.e.v8.V8GCStatsThreadSlice) continue; + const liveObjects = slice.liveObjects; + const deadObjects = slice.deadObjects; + const isolate = liveObjects.isolate; + + const isolateEntry = + new GroupedEntry( + 'Isolate_' + isolate + ' at ' + slice.start.toFixed(3) + ' ms', + 0, 0, 0, [], []); + const liveEntry = new GroupedEntry('live objects', 0, 0, 0, [], []); + const deadEntry = new GroupedEntry('dead objects', 0, 0, 0, [], []); + + const liveBucketSize = liveObjects.bucket_sizes.length; + const deadBucketSize = deadObjects.bucket_sizes.length; + + this.build_(tr.b.deepCopy(liveObjects.type_data), liveEntry, + liveBucketSize); + isolateEntry.add(liveEntry); + + this.build_(tr.b.deepCopy(deadObjects.type_data), deadEntry, + deadBucketSize); + isolateEntry.add(deadEntry); + + isolateEntry.calculatePercentage(); + this.isolateEntries_.push(isolateEntry); + } + this.updateTable_(); + + if (slices.length > 1) { + this.buildOptions_(); + this.constructDiffTable_(); + } + }, + + updateTable_() { + this.constructTable_(); + this.$.table.tableRows = this.isolateEntries_; + this.$.table.rebuild(); + }, + }); + + return {}; +}); +</script> |