Commit 7413658c authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Improve system-analyzer

- Fix State timerange adjustment for multiple timelines
- Fix grid layout for detail panels
- Style panels consistently
- Simplify file-reader html

Bug: v8:10644
Change-Id: I277d88e2deb2bf71b0204034f6e63ea35f85a791
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2485812
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70653}
parent 403390ec
...@@ -13,6 +13,7 @@ class State { ...@@ -13,6 +13,7 @@ class State {
_chunks; _chunks;
_icTimeline; _icTimeline;
_mapTimeline; _mapTimeline;
_deoptTimeline;
_minStartTime = Number.POSITIVE_INFINITY; _minStartTime = Number.POSITIVE_INFINITY;
_maxEndTime = Number.NEGATIVE_INFINITY; _maxEndTime = Number.NEGATIVE_INFINITY;
get minStartTime() { get minStartTime() {
...@@ -21,27 +22,41 @@ class State { ...@@ -21,27 +22,41 @@ class State {
get maxEndTime() { get maxEndTime() {
return this._maxEndTime; return this._maxEndTime;
} }
selectTimeRange(start, end) {
this.timeSelection.start = start;
this.timeSelection.end = end;
this._icTimeline.selectTimeRange(start, end);
this._mapTimeline.selectTimeRange(start, end);
this._deoptTimeline.selectTimeRange(start, end);
}
_updateTimeRange(timeline) { _updateTimeRange(timeline) {
this._minStartTime = Math.min(this._minStartTime, timeline.startTime); this._minStartTime = Math.min(this._minStartTime, timeline.startTime);
this._maxEndTime = Math.max(this._maxEndTime, timeline.endTime); this._maxEndTime = Math.max(this._maxEndTime, timeline.endTime);
timeline.startTime = this._minStartTime;
timeline.endTime = this._maxEndTime;
} }
get mapTimeline() { get mapTimeline() {
return this._mapTimeline; return this._mapTimeline;
} }
set mapTimeline(timeline) { set mapTimeline(timeline) {
this._updateTimeRange(timeline); this._updateTimeRange(timeline);
timeline.startTime = this._minStartTime;
timeline.endTime = this._maxEndTime;
this._mapTimeline = timeline; this._mapTimeline = timeline;
} }
get icTimeline() {
return this._icTimeline;
}
set icTimeline(timeline) { set icTimeline(timeline) {
this._updateTimeRange(timeline); this._updateTimeRange(timeline);
timeline.startTime = this._minStartTime;
timeline.endTime = this._maxEndTime;
this._icTimeline = timeline; this._icTimeline = timeline;
} }
get icTimeline() { get deoptTimeline() {
return this._icTimeline; return this._deoptTimeline;
}
set deoptTimeline(timeline) {
this._updateTimeRange(timeline);
this._deoptTimeline = timeline;
} }
set chunks(value) { set chunks(value) {
//TODO(zcankara) split up between maps and ics, and every timeline track //TODO(zcankara) split up between maps and ics, and every timeline track
......
...@@ -46,11 +46,14 @@ body { ...@@ -46,11 +46,14 @@ body {
font-family: "Roboto", sans-serif; font-family: "Roboto", sans-serif;
font-size: 14px; font-size: 14px;
color: var(--on-background-color); color: var(--on-background-color);
margin-left: 2.5%; margin: 10px 10px 0 10px;
margin-right: 2.5%;
background-color: var(--background-color); background-color: var(--background-color);
} }
section {
margin-bottom: 10px;
}
::-webkit-scrollbar, ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { ::-webkit-scrollbar, ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner {
background-color: rgba(0, 0, 0, 0.0); background-color: rgba(0, 0, 0, 0.0);
} }
...@@ -58,7 +61,7 @@ body { ...@@ -58,7 +61,7 @@ body {
width: 10px; width: 10px;
height: 10px; height: 10px;
} }
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
background-color: rgba(128, 128, 128, 0.5); background-color: rgba(128, 128, 128, 0.5);
border-radius: 8px; border-radius: 8px;
cursor: pointer; cursor: pointer;
...@@ -104,11 +107,16 @@ dd { ...@@ -104,11 +107,16 @@ dd {
} }
.panel { .panel {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
background-color: var(--surface-color); background-color: var(--surface-color);
color: var(--on-surface-color); color: var(--on-surface-color);
padding: 10px 10px 10px 10px; padding: 10px 10px 10px 10px;
overflow-x: auto; overflow-x: auto;
border-radius: 10px;
border: 3px solid rgba(128, 128, 128, 0.2);
}
.panel > h2 {
margin-top: 5px;
} }
button { button {
......
...@@ -58,19 +58,19 @@ found in the LICENSE file. --> ...@@ -58,19 +58,19 @@ found in the LICENSE file. -->
display: none; display: none;
} }
#container.loaded { #timeline-panel {
width: 100%;
}
.panels{
display: grid; display: grid;
align-content: center; align-content: center;
grid-template-columns: repeat(auto-fit, minmax(400px, 800px)); grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
grid-template-rows: repeat(auto-fit, minmax(400px, 800px)); grid-auto-flow: row dense;
grid-auto-flow: dense; grid-gap: 10px;
grid-gap: 1em; margin-top: 10px;
} }
#container.loaded>#timeline-panel {
grid-column: span 2;
overflow: scroll;
}
dt::after { dt::after {
content: ":"; content: ":";
} }
...@@ -95,82 +95,86 @@ found in the LICENSE file. --> ...@@ -95,82 +95,86 @@ found in the LICENSE file. -->
<timeline-track id="ic-track"></timeline-track> <timeline-track id="ic-track"></timeline-track>
<timeline-track id="deopt-track"></timeline-track> <timeline-track id="deopt-track"></timeline-track>
</timeline-panel> </timeline-panel>
<map-panel id="map-panel"></map-panel> <div class="panels">
<ic-panel id="ic-panel" onchange="app.handleSelectIc(event)"></ic-panel> <map-panel id="map-panel"></map-panel>
<source-panel id="source-panel"></source-panel> <ic-panel id="ic-panel" onchange="app.handleSelectIc(event)"></ic-panel>
</section> <source-panel id="source-panel"></source-panel>
<section id="settings">
<h2>Settings</h2>
<span>Theme:</span>
<div class="theme-switch-wrapper">
<label class="theme-switch" for="theme-switch-input">
<input type="checkbox" id="theme-switch-input" />
<div class="slider"></div>
</label>
</div> </div>
</section> </section>
<section id="instructions"> <div class="panels">
<h2>Instructions</h2> <section id="settings" class="panel">
<p> <h2>Settings</h2>
Unified web interface to analyse runtime information stored in the v8 log. <span>Theme:</span>
</p> <div class="theme-switch-wrapper">
For generating a v8.log file from <a href="https://v8.dev/docs/build">d8</a>: <label class="theme-switch" for="theme-switch-input">
<ul> <input type="checkbox" id="theme-switch-input" />
<li> <div class="slider"></div>
<code>/path/do/d8 --trace-maps --trace_ic --log-source-code $FILE</code> </label>
</li> </div>
</ul> </section>
For generating a v8.log file from Chrome:
<ul> <section id="instructions" class="panel">
<li> <h2>Instructions</h2>
<code>/path/to/chrome --user-data-dir=/var/tmp/chr$RANDOM --no-sandbox <p>
--js-flags='--trace-ic --trace-maps --log-source-code’ Unified web interface to analyse runtime information stored in the v8 log.
$WEBSITE_URL</code> </p>
</li> For generating a v8.log file from <a href="https://v8.dev/docs/build">d8</a>:
</ul> <ul>
<li>
<h3>Log Options:</h3> <code>/path/do/d8 --trace-maps --trace_ic --log-source-code $FILE</code>
<dl class="d8-options"> </li>
<dt><code>--trace-maps</code></dt> </ul>
<dd>Log<a href="https://v8.dev/blog/fast-properties" target="_blank"> For generating a v8.log file from Chrome:
Maps</a></dd> <ul>
<dt><code>--trace-ic</code></dt> <li>
<dd>Log <code>/path/to/chrome --user-data-dir=/var/tmp/chr$RANDOM --no-sandbox
<a href="https://mathiasbynens.be/notes/shapes-ics" target="_blank"> --js-flags='--trace-ic --trace-maps --log-source-code’
ICs</a></dd> $WEBSITE_URL</code>
<dt><code>--log-source-code</code></dt> </li>
<dd>Log source code</dd> </ul>
</dl>
<h3>Log Options:</h3>
<h3>Keyboard Shortcuts for Navigation</h3> <dl class="d8-options">
<dl> <dt><code>--trace-maps</code></dt>
<dt><kbd>SHIFT</kbd> + <kbd>Arrow Up</kbd></dt> <dd>Log<a href="https://v8.dev/blog/fast-properties" target="_blank">
<dd>Follow Map transition forward (first child)</dd> Maps</a></dd>
<dt><code>--trace-ic</code></dt>
<dt><kbd>SHIFT</kbd> + <kbd>Arrow Down</kbd></dt> <dd>Log
<dd>Follow Map transition backwards</dd> <a href="https://mathiasbynens.be/notes/shapes-ics" target="_blank">
ICs</a></dd>
<dt><kbd>Arrow Up</kbd></dt> <dt><code>--log-source-code</code></dt>
<dd>Go to previous Map chunk</dd> <dd>Log source code</dd>
</dl>
<dt><kbd>Arrow Down</kbd></dt>
<dd>Go to next Map in chunk</dd> <h3>Keyboard Shortcuts for Navigation</h3>
<dl>
<dt><kbd>Arrow Left</kbd></dt> <dt><kbd>SHIFT</kbd> + <kbd>Arrow Up</kbd></dt>
<dd>Go to previous chunk</dd> <dd>Follow Map transition forward (first child)</dd>
<dt><kbd>Arrow Right</kbd></dt> <dt><kbd>SHIFT</kbd> + <kbd>Arrow Down</kbd></dt>
<dd>Go to next chunk</dd> <dd>Follow Map transition backwards</dd>
<dt><kbd>+</kbd></dt> <dt><kbd>Arrow Up</kbd></dt>
<dd>Timeline zoom in</dd> <dd>Go to previous Map chunk</dd>
<dt><kbd>-</kbd></dt> <dt><kbd>Arrow Down</kbd></dt>
<dd>Timeline zoom out</dd> <dd>Go to next Map in chunk</dd>
</dl>
</section> <dt><kbd>Arrow Left</kbd></dt>
<dd>Go to previous chunk</dd>
<dt><kbd>Arrow Right</kbd></dt>
<dd>Go to next chunk</dd>
<dt><kbd>+</kbd></dt>
<dd>Timeline zoom in</dd>
<dt><kbd>-</kbd></dt>
<dd>Timeline zoom out</dd>
</dl>
</section>
</div>
</body> </body>
</html> </html>
...@@ -24,6 +24,7 @@ class App { ...@@ -24,6 +24,7 @@ class App {
constructor(fileReaderId, mapPanelId, timelinePanelId, constructor(fileReaderId, mapPanelId, timelinePanelId,
icPanelId, mapTrackId, icTrackId, deoptTrackId, sourcePanelId) { icPanelId, mapTrackId, icTrackId, deoptTrackId, sourcePanelId) {
this._view = { this._view = {
__proto__: null,
logFileReader: $(fileReaderId), logFileReader: $(fileReaderId),
icPanel: $(icPanelId), icPanel: $(icPanelId),
mapPanel: $(mapPanelId), mapPanel: $(mapPanelId),
...@@ -40,10 +41,10 @@ class App { ...@@ -40,10 +41,10 @@ class App {
this.toggleSwitch = $('.theme-switch input[type="checkbox"]'); this.toggleSwitch = $('.theme-switch input[type="checkbox"]');
this.toggleSwitch.addEventListener("change", (e) => this.switchTheme(e)); this.toggleSwitch.addEventListener("change", (e) => this.switchTheme(e));
this._view.logFileReader.addEventListener("fileuploadstart", (e) => this._view.logFileReader.addEventListener("fileuploadstart", (e) =>
this.handleFileUpload(e) this.handleFileUploadStart(e)
); );
this._view.logFileReader.addEventListener("fileuploadend", (e) => this._view.logFileReader.addEventListener("fileuploadend", (e) =>
this.handleDataUpload(e) this.handleFileUploadEnd(e)
); );
Object.entries(this._view).forEach(([_, panel]) => { Object.entries(this._view).forEach(([_, panel]) => {
panel.addEventListener(SelectionEvent.name, panel.addEventListener(SelectionEvent.name,
...@@ -67,15 +68,15 @@ class App { ...@@ -67,15 +68,15 @@ class App {
} }
showMapEntries(entries) { showMapEntries(entries) {
this._state.selectedMapLogEntries = entries; this._state.selectedMapLogEntries = entries;
this._view.mapPanel.selectedMapLogEntries = this.#state.selectedMapLogEntries; this._view.mapPanel.selectedMapLogEntries = entries;
} }
showIcEntries(entries) { showIcEntries(entries) {
this._state.selectedIcLogEntries = entries; this._state.selectedIcLogEntries = entries;
this._view.icPanel.selectedLogEntries = this.#state.selectedIcLogEntries; this._view.icPanel.selectedLogEntries = entries;
} }
showSourcePositionEntries(entries) { showSourcePositionEntries(entries) {
//TODO(zcankara) Handle multiple source position selection events //TODO: Handle multiple source position selection events
this._view.sourcePanel.selectedSourcePositions = entries; this._view.sourcePanel.selectedSourcePositions = entries
} }
handleTimeRangeSelect(e) { handleTimeRangeSelect(e) {
...@@ -93,12 +94,9 @@ class App { ...@@ -93,12 +94,9 @@ class App {
} }
} }
selectTimeRange(start, end) { selectTimeRange(start, end) {
this._state.timeSelection.start = start; this._state.selectTimeRange(start, end);
this._state.timeSelection.end = end; this._view.mapPanel.selectedMapLogEntries =
this._state.icTimeline.selectTimeRange(start, end); this._state.mapTimeline.selection;
this._state.mapTimeline.selectTimeRange(start, end);
this._view.mapPanel.selectedMapLogEntries =
this._state.mapTimeline.selection;
this._view.icPanel.selectedLogEntries = this._state.icTimeline.selection; this._view.icPanel.selectedLogEntries = this._state.icTimeline.selection;
} }
selectMapLogEntry(entry) { selectMapLogEntry(entry) {
...@@ -115,7 +113,7 @@ class App { ...@@ -115,7 +113,7 @@ class App {
this._view.sourcePanel.selectedSourcePositions = [sourcePositions]; this._view.sourcePanel.selectedSourcePositions = [sourcePositions];
} }
handleFileUpload(e) { handleFileUploadStart(e) {
this.restartApp(); this.restartApp();
$("#container").className = "initial"; $("#container").className = "initial";
} }
...@@ -125,32 +123,22 @@ class App { ...@@ -125,32 +123,22 @@ class App {
this._navigation = new Navigation(this._state, this._view); this._navigation = new Navigation(this._state, this._view);
} }
// Event log processing handleFileUploadEnd(e) {
handleLoadTextProcessor(text) {
let logProcessor = new Processor();
logProcessor.processString(text);
return logProcessor;
}
// call when a new file uploaded
handleDataUpload(e) {
if (!e.detail) return; if (!e.detail) return;
$("#container").className = "loaded"; $("#container").className = "loaded";
// instantiate the app logic // instantiate the app logic
let fileData = e.detail; let fileData = e.detail;
const processor = this.handleLoadTextProcessor(fileData.chunk); const processor = new Processor(fileData.chunk);
const mapTimeline = processor.mapTimeline; const mapTimeline = processor.mapTimeline;
const icTimeline = processor.icTimeline; const icTimeline = processor.icTimeline;
const deoptTimeline = processor.deoptTimeline; const deoptTimeline = processor.deoptTimeline;
// Load map log events timeline.
this._state.mapTimeline = mapTimeline; this._state.mapTimeline = mapTimeline;
this._state.icTimeline = icTimeline;
this._state.deoptTimeline = deoptTimeline;
// Transitions must be set before timeline for stats panel. // Transitions must be set before timeline for stats panel.
this._view.mapPanel.transitions = this._state.mapTimeline.transitions; this._view.mapPanel.transitions = this._state.mapTimeline.transitions;
this._view.mapTrack.data = mapTimeline; this._view.mapTrack.data = mapTimeline;
this._state.chunks = this._view.mapTrack.chunks;
this._view.mapPanel.timeline = mapTimeline; this._view.mapPanel.timeline = mapTimeline;
// Load ic log events timeline.
this._state.icTimeline = icTimeline;
this._view.icPanel.timeline = icTimeline; this._view.icPanel.timeline = icTimeline;
this._view.icTrack.data = icTimeline; this._view.icTrack.data = icTimeline;
this._view.deoptTrack.data = deoptTimeline; this._view.deoptTrack.data = deoptTimeline;
...@@ -161,6 +149,7 @@ class App { ...@@ -161,6 +149,7 @@ class App {
refreshTimelineTrackView() { refreshTimelineTrackView() {
this._view.mapTrack.data = this._state.mapTimeline; this._view.mapTrack.data = this._state.mapTimeline;
this._view.icTrack.data = this._state.icTimeline; this._view.icTrack.data = this._state.icTimeline;
this._view.deoptTrack.data = this._state.deoptTimeline;
} }
switchTheme(event) { switchTheme(event) {
...@@ -186,7 +175,7 @@ class Navigation { ...@@ -186,7 +175,7 @@ class Navigation {
this.state.map = value this.state.map = value
} }
get chunks() { get chunks() {
return this.state.chunks return this.state.mapTimeline.chunks;
} }
increaseTimelineResolution() { increaseTimelineResolution() {
this._view.timelinePanel.nofChunks *= 1.5; this._view.timelinePanel.nofChunks *= 1.5;
......
...@@ -7,14 +7,11 @@ found in the LICENSE file. --> ...@@ -7,14 +7,11 @@ found in the LICENSE file. -->
</head> </head>
<style> <style>
#fileReader { #fileReader {
width: 100%;
height: 100px; height: 100px;
line-height: 100px; line-height: 100px;
text-align: center; text-align: center;
border-radius: 5px;
cursor: pointer; cursor: pointer;
transition: all 0.5s ease-in-out; transition: all 0.5s ease-in-out;
border: 2px solid var(--primary-color);
background-color: var(--surface-color); background-color: var(--surface-color);
} }
...@@ -74,15 +71,12 @@ found in the LICENSE file. --> ...@@ -74,15 +71,12 @@ found in the LICENSE file. -->
} }
} }
</style> </style>
<div id="fileReader" class="panel" tabindex=1>
<section id="fileReaderSection"> <span id="label">
<div id="fileReader" tabindex=1> Drag and drop a v8.log file into this area, or click to choose from disk.
<span id="label"> </span>
Drag and drop a v8.log file into this area, or click to choose from disk. <input id="file" type="file" name="file">
</span> </div>
<input id="file" type="file" name="file"> <div id="loader">
</div> <div id="spinner"></div>
<div id="loader"> </div>
<div id="spinner"></div>
</div>
</section>
...@@ -15,10 +15,6 @@ defineCustomElement('log-file-reader', (templateText) => ...@@ -15,10 +15,6 @@ defineCustomElement('log-file-reader', (templateText) =>
e => this.handleKeyEvent(e)); e => this.handleKeyEvent(e));
} }
get section() {
return this.$('#fileReaderSection');
}
updateLabel(text) { updateLabel(text) {
this.$('#label').innerText = text; this.$('#label').innerText = text;
} }
...@@ -54,7 +50,7 @@ defineCustomElement('log-file-reader', (templateText) => ...@@ -54,7 +50,7 @@ defineCustomElement('log-file-reader', (templateText) =>
return; return;
} }
this.$('#fileReader').blur(); this.$('#fileReader').blur();
this.section.className = 'loading'; this.shadowRoot.className = 'loading';
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => {
try { try {
...@@ -67,11 +63,11 @@ defineCustomElement('log-file-reader', (templateText) => ...@@ -67,11 +63,11 @@ defineCustomElement('log-file-reader', (templateText) =>
bubbles: true, composed: true, bubbles: true, composed: true,
detail: dataModel detail: dataModel
})); }));
this.section.className = 'success'; this.shadowRoot.className = 'success';
this.$('#fileReader').classList.add('done'); this.$('#fileReader').classList.add('done');
} catch (err) { } catch (err) {
console.error(err); console.error(err);
this.section.className = 'failure'; this.shadowRoot.className = 'failure';
} }
}; };
// Delay the loading a bit to allow for CSS animations to happen. // Delay the loading a bit to allow for CSS animations to happen.
......
...@@ -19,7 +19,7 @@ export class Processor extends LogReader { ...@@ -19,7 +19,7 @@ export class Processor extends LogReader {
_formatPCRegexp = /(.*):[0-9]+:[0-9]+$/; _formatPCRegexp = /(.*):[0-9]+:[0-9]+$/;
MAJOR_VERSION = 7; MAJOR_VERSION = 7;
MINOR_VERSION = 6; MINOR_VERSION = 6;
constructor() { constructor(logString) {
super(); super();
this.propertyICParser = [ this.propertyICParser = [
parseInt, parseInt, parseInt, parseInt, parseString, parseString, parseInt, parseInt, parseInt, parseInt, parseString, parseString,
...@@ -98,6 +98,7 @@ export class Processor extends LogReader { ...@@ -98,6 +98,7 @@ export class Processor extends LogReader {
processor: this.processPropertyIC.bind(this, 'StoreInArrayLiteralIC') processor: this.processPropertyIC.bind(this, 'StoreInArrayLiteralIC')
}, },
}; };
if (logString) this.processString(logString);
} }
printError(str) { printError(str) {
......
...@@ -12,7 +12,6 @@ found in the LICENSE file. --> ...@@ -12,7 +12,6 @@ found in the LICENSE file. -->
overflow-y: hidden; overflow-y: hidden;
overflow-x: scroll; overflow-x: scroll;
user-select: none; user-select: none;
background-color: var(--timeline-background-color);
} }
#timelineLabel { #timelineLabel {
...@@ -66,15 +65,16 @@ found in the LICENSE file. --> ...@@ -66,15 +65,16 @@ found in the LICENSE file. -->
max-width: 280px; max-width: 280px;
padding-left: 20px; padding-left: 20px;
padding-top: 10px; padding-top: 10px;
border-collapse: collapse;
} }
th, th,
td { td {
width: 200px; width: 200px;
text-align: left; text-align: left;
padding-bottom: 1px; padding-bottom: 3px;
} }
/* right align numbers */ /* right align numbers */
#legend td:nth-of-type(4n+3), #legend td:nth-of-type(4n+3),
#legend td:nth-of-type(4n+4) { #legend td:nth-of-type(4n+4) {
...@@ -88,7 +88,7 @@ found in the LICENSE file. --> ...@@ -88,7 +88,7 @@ found in the LICENSE file. -->
.timeline { .timeline {
background-color: var(--timeline-background-color); background-color: var(--timeline-background-color);
} }
#timeline .rightHandle, #timeline .rightHandle,
#timeline .leftHandle { #timeline .leftHandle {
background-color: rgba(200, 200, 200, 0.5); background-color: rgba(200, 200, 200, 0.5);
...@@ -106,7 +106,7 @@ found in the LICENSE file. --> ...@@ -106,7 +106,7 @@ found in the LICENSE file. -->
z-index: 2; z-index: 2;
} }
</style> </style>
<div class="timeline"> <div>
<table id="legend"> <table id="legend">
<thead> <thead>
<tr> <tr>
......
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