Commit eb6b3b49 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Improve system-analyzer startup and loader

- Display spinner properly again
- Defer loadding additional App and subsequent modules
- Preload file reader module and template

Change-Id: Ifc81a93864d61c282db90df25f93dc0eefef4373
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494925
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70730}
parent 80ec52ea
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
} }
body { body {
font-family: "Roboto", sans-serif; font-family: sans-serif;
font-size: 14px; font-size: 14px;
color: var(--on-background-color); color: var(--on-background-color);
margin: 10px 10px 0 10px; margin: 10px 10px 0 10px;
......
...@@ -2,14 +2,27 @@ ...@@ -2,14 +2,27 @@
<!-- Copyright 2020 the V8 project authors. All rights reserved. <!-- Copyright 2020 the V8 project authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. --> found in the LICENSE file. -->
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Indicium</title> <title>Indicium</title>
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
<!-- <link rel="icon" type="image/png" href="/images/favicon.png"/> --> <!-- <link rel="icon" type="image/png" href="/images/favicon.png"/> -->
<link rel="modulepreload" href="./log-file-reader.mjs" >
<link rel="modulepreload" href="./helper.mjs" >
<link rel="preload" href="./log-file-reader-template.html" as="fetch" crossorigin="anonymous">
<script type="module">
// Force instatiating the log-reader before anything else.
import "./log-file-reader.mjs";
// Delay loading of the main App
(async function() {
let module = await import('./index.mjs');
globalThis.app = new module.App("#log-file-reader", "#map-panel", "#map-stats-panel",
"#timeline-panel", "#ic-panel", "#map-track", "#ic-track", "#deopt-track",
"#source-panel");
})();
</script>
<link rel="stylesheet" type="text/css" href="./index.css"> <link rel="stylesheet" type="text/css" href="./index.css">
<style> <style>
.theme-switch-wrapper { .theme-switch-wrapper {
...@@ -75,13 +88,6 @@ found in the LICENSE file. --> ...@@ -75,13 +88,6 @@ found in the LICENSE file. -->
content: ":"; content: ":";
} }
</style> </style>
<script type="module">
import { App } from './index.mjs';
globalThis.app = new App("#log-file-reader", "#map-panel", "#map-stats-panel",
"#timeline-panel", "#ic-panel", "#map-track", "#ic-track", "#deopt-track",
"#source-panel");
</script>
</head> </head>
<body> <body>
...@@ -177,5 +183,4 @@ found in the LICENSE file. --> ...@@ -177,5 +183,4 @@ found in the LICENSE file. -->
</section> </section>
</div> </div>
</body> </body>
</html> </html>
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import { SelectionEvent, FocusEvent, SelectTimeEvent } from "./events.mjs"; import { SelectionEvent, FocusEvent, SelectTimeEvent } from "./events.mjs";
import { State } from "./app-model.mjs"; import { State } from "./app-model.mjs";
import { MapLogEntry } from "./log/map.mjs"; import { MapLogEntry } from "./log/map.mjs";
...@@ -10,18 +9,13 @@ import { IcLogEntry } from "./log/ic.mjs"; ...@@ -10,18 +9,13 @@ import { IcLogEntry } from "./log/ic.mjs";
import { Processor } from "./processor.mjs"; import { Processor } from "./processor.mjs";
import { SourcePosition } from "../profile.mjs"; import { SourcePosition } from "../profile.mjs";
import { $ } from "./helper.mjs"; import { $ } from "./helper.mjs";
import "./ic-panel.mjs";
import "./timeline-panel.mjs";
import "./stats-panel.mjs";
import "./map-panel.mjs";
import "./log-file-reader.mjs";
import "./source-panel.mjs";
class App { class App {
_state; _state;
_view; _view;
_navigation; _navigation;
_startupPromise;
constructor(fileReaderId, mapPanelId, mapStatsPanelId, timelinePanelId, constructor(fileReaderId, mapPanelId, mapStatsPanelId, timelinePanelId,
icPanelId, mapTrackId, icTrackId, deoptTrackId, sourcePanelId) { icPanelId, mapTrackId, icTrackId, deoptTrackId, sourcePanelId) {
this._view = { this._view = {
...@@ -36,10 +30,6 @@ class App { ...@@ -36,10 +30,6 @@ class App {
deoptTrack: $(deoptTrackId), deoptTrack: $(deoptTrackId),
sourcePanel: $(sourcePanelId) sourcePanel: $(sourcePanelId)
}; };
this._state = new State();
this._navigation = new Navigation(this._state, this._view);
document.addEventListener('keydown',
e => this._navigation.handleKeyDown(e));
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) =>
...@@ -48,6 +38,19 @@ class App { ...@@ -48,6 +38,19 @@ class App {
this._view.logFileReader.addEventListener("fileuploadend", (e) => this._view.logFileReader.addEventListener("fileuploadend", (e) =>
this.handleFileUploadEnd(e) this.handleFileUploadEnd(e)
); );
this._startupPromise = this.runAsyncInitialize();
}
async runAsyncInitialize() {
await Promise.all([
import("./ic-panel.mjs"),
import("./timeline-panel.mjs"),
import("./stats-panel.mjs"),
import("./map-panel.mjs"),
import("./source-panel.mjs"),
]);
document.addEventListener('keydown',
e => this._navigation?.handleKeyDown(e));
Object.entries(this._view).forEach(([_, panel]) => { Object.entries(this._view).forEach(([_, panel]) => {
panel.addEventListener(SelectionEvent.name, panel.addEventListener(SelectionEvent.name,
e => this.handleShowEntries(e)); e => this.handleShowEntries(e));
...@@ -57,6 +60,7 @@ class App { ...@@ -57,6 +60,7 @@ class App {
e => this.handleTimeRangeSelect(e)); e => this.handleTimeRangeSelect(e));
}); });
} }
handleShowEntries(e) { handleShowEntries(e) {
if (e.entries[0] instanceof MapLogEntry) { if (e.entries[0] instanceof MapLogEntry) {
this.showMapEntries(e.entries); this.showMapEntries(e.entries);
...@@ -134,27 +138,29 @@ class App { ...@@ -134,27 +138,29 @@ class App {
this._navigation = new Navigation(this._state, this._view); this._navigation = new Navigation(this._state, this._view);
} }
handleFileUploadEnd(e) { async handleFileUploadEnd(e) {
if (!e.detail) return; await this._startupPromise;
try {
const processor = new Processor(e.detail);
const mapTimeline = processor.mapTimeline;
const icTimeline = processor.icTimeline;
const deoptTimeline = processor.deoptTimeline;
this._state.mapTimeline = mapTimeline;
this._state.icTimeline = icTimeline;
this._state.deoptTimeline = deoptTimeline;
// Transitions must be set before timeline for stats panel.
this._view.mapPanel.timeline = mapTimeline;
this._view.mapTrack.data = mapTimeline;
this._view.mapStatsPanel.transitions = this._state.mapTimeline.transitions;
this._view.mapStatsPanel.timeline = mapTimeline;
this._view.icPanel.timeline = icTimeline;
this._view.icTrack.data = icTimeline;
this._view.deoptTrack.data = deoptTimeline;
this._view.sourcePanel.data = processor.scripts
} catch(e) {
this._view.logFileReader.error = "Log file contains errors!"
}
$("#container").className = "loaded"; $("#container").className = "loaded";
// instantiate the app logic
let fileData = e.detail;
const processor = new Processor(fileData.chunk);
const mapTimeline = processor.mapTimeline;
const icTimeline = processor.icTimeline;
const deoptTimeline = processor.deoptTimeline;
this._state.mapTimeline = mapTimeline;
this._state.icTimeline = icTimeline;
this._state.deoptTimeline = deoptTimeline;
// Transitions must be set before timeline for stats panel.
this._view.mapPanel.timeline = mapTimeline;
this._view.mapTrack.data = mapTimeline;
this._view.mapStatsPanel.transitions = this._state.mapTimeline.transitions;
this._view.mapStatsPanel.timeline = mapTimeline;
this._view.icPanel.timeline = icTimeline;
this._view.icTrack.data = icTimeline;
this._view.deoptTrack.data = deoptTimeline;
this._view.sourcePanel.data = processor.scripts
this.fileLoaded = true; this.fileLoaded = true;
} }
......
...@@ -14,16 +14,19 @@ found in the LICENSE file. --> ...@@ -14,16 +14,19 @@ found in the LICENSE file. -->
transition: all 0.5s ease-in-out; transition: all 0.5s ease-in-out;
background-color: var(--surface-color); background-color: var(--surface-color);
} }
#fileReader:hover {
background-color: var(--primary-color);
color: var(--on-primary-color);
}
#fileReader.done { .done #fileReader{
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
} }
#fileReader:hover { .fail #fileReader {
background-color: var(--primary-color); background-color: var(--error-color);
color: var(--on-primary-color);
} }
.loading #fileReader { .loading #fileReader {
...@@ -47,7 +50,6 @@ found in the LICENSE file. --> ...@@ -47,7 +50,6 @@ found in the LICENSE file. -->
height: 100%; height: 100%;
background-color: var(--file-reader-background-color); background-color: var(--file-reader-background-color);
} }
#spinner { #spinner {
position: absolute; position: absolute;
width: 100px; width: 100px;
...@@ -71,12 +73,14 @@ found in the LICENSE file. --> ...@@ -71,12 +73,14 @@ found in the LICENSE file. -->
} }
} }
</style> </style>
<div id="fileReader" class="panel" tabindex=1> <div id="root">
<span id="label"> <div id="fileReader" class="panel" 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 id="spinner"></div>
</div>
</div> </div>
...@@ -15,6 +15,11 @@ defineCustomElement('log-file-reader', (templateText) => ...@@ -15,6 +15,11 @@ defineCustomElement('log-file-reader', (templateText) =>
e => this.handleKeyEvent(e)); e => this.handleKeyEvent(e));
} }
set error(message) {
this.updateLabel(message);
this.root.className = 'fail';
}
updateLabel(text) { updateLabel(text) {
this.$('#label').innerText = text; this.$('#label').innerText = text;
} }
...@@ -41,36 +46,37 @@ defineCustomElement('log-file-reader', (templateText) => ...@@ -41,36 +46,37 @@ defineCustomElement('log-file-reader', (templateText) =>
} }
connectedCallback() { connectedCallback() {
this.$('#fileReader').focus(); this.fileReader.focus();
}
get fileReader() {
return this.$('#fileReader');
} }
get root() { return this.$("#root"); }
readFile(file) { readFile(file) {
if (!file) { if (!file) {
this.updateLabel('Failed to load file.'); this.error = 'Failed to load file.';
return; return;
} }
this.$('#fileReader').blur(); this.fileReader.blur();
this.shadowRoot.className = 'loading'; this.root.className = 'loading';
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => this.handleFileLoad(e, file);
try {
let dataModel = Object.create(null);
dataModel.file = file;
dataModel.chunk = e.target.result;
this.updateLabel('Finished loading \'' + file.name + '\'.');
this.dispatchEvent(new CustomEvent(
'fileuploadend', {
bubbles: true, composed: true,
detail: dataModel
}));
this.shadowRoot.className = 'success';
this.$('#fileReader').classList.add('done');
} catch (err) {
console.error(err);
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.
setTimeout(() => reader.readAsText(file), 0); setTimeout(() => reader.readAsText(file), 0);
} }
handleFileLoad(e, file) {
const chunk = e.target.result;
this.updateLabel('Finished loading \'' + file.name + '\'.');
this.dispatchEvent(new CustomEvent(
'fileuploadend', {
bubbles: true,
composed: true,
detail: chunk,
}));
this.root.className = 'done';
}
}); });
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