add "timeline" system for measuring app start performance
This commit is contained in:
parent
be560e5510
commit
17e086769d
8 changed files with 72 additions and 1 deletions
|
@ -1,6 +1,7 @@
|
|||
import gateway, { GatewayEventType } from "./gateway";
|
||||
import { removeItem, setItem } from "./storage";
|
||||
import { overlayStore, OverlayType } from "./stores";
|
||||
import { timeline } from "./timeline";
|
||||
|
||||
export function useAuthHandlers() {
|
||||
gateway.subscribe(GatewayEventType.Ready, () => {
|
||||
|
@ -14,6 +15,7 @@ export function useAuthHandlers() {
|
|||
}
|
||||
|
||||
export function authWithToken(token, shouldUpdate=false) {
|
||||
timeline.addCheckpoint("Authentication started (authWithToken)");
|
||||
if (shouldUpdate)
|
||||
setItem("auth:token", token);
|
||||
gateway.init(token);
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
<script>
|
||||
import { afterUpdate, beforeUpdate } from "svelte";
|
||||
import { showSidebar, selectedChannel, smallViewport, showChannelView, theme, showPresenceSidebar } from "../stores";
|
||||
import { timeline } from "../timeline";
|
||||
import ChannelView from "./ChannelView.svelte";
|
||||
import OverlayProvider from "./overlays/OverlayProvider.svelte";
|
||||
import PresenceSidebar from "./PresenceSidebar.svelte";
|
||||
import Sidebar from "./Sidebar.svelte";
|
||||
|
||||
beforeUpdate(() => {
|
||||
timeline.addCheckpoint("Main component update start");
|
||||
});
|
||||
|
||||
afterUpdate(() => {
|
||||
timeline.addCheckpoint("Main component update end");
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
|
|
@ -2,6 +2,7 @@ import gateway from './gateway';
|
|||
import { getItem, init, setItem, removeItem } from './storage';
|
||||
import { allStores } from './stores';
|
||||
import { authWithToken, logOut } from './auth';
|
||||
import { timeline } from './timeline';
|
||||
|
||||
export function useDebuggingApi() {
|
||||
window.__waffle = {
|
||||
|
@ -16,6 +17,7 @@ export function useDebuggingApi() {
|
|||
authWithToken,
|
||||
logOut
|
||||
},
|
||||
timeline,
|
||||
stores: allStores,
|
||||
app: null
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import logger from "./logging";
|
||||
import { getItem } from "./storage";
|
||||
import { timeline } from "./timeline";
|
||||
|
||||
export const GatewayErrors = {
|
||||
BAD_PAYLOAD: 4001,
|
||||
|
@ -58,6 +59,7 @@ export default {
|
|||
handlers: new Map(),
|
||||
disableReconnect: false,
|
||||
init(token) {
|
||||
timeline.addCheckpoint("Gateway connection start");
|
||||
if (!token) {
|
||||
log("no auth token, skipping connection");
|
||||
this.dispatch(GatewayEventType.Close, GatewayErrors.BAD_AUTH);
|
||||
|
@ -67,6 +69,7 @@ export default {
|
|||
log(`connecting to gateway - gatewayBase: ${getItem("server:gatewayBase")}`);
|
||||
this.ws = new WebSocket(getItem("server:gatewayBase"));
|
||||
this.ws.onopen = () => {
|
||||
timeline.addCheckpoint("Gateway connection open");
|
||||
if (this.reconnectTimeout) {
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
}
|
||||
|
@ -80,6 +83,7 @@ export default {
|
|||
|
||||
switch (payload.t) {
|
||||
case GatewayPayloadType.Hello: {
|
||||
timeline.addCheckpoint("Gateway hello");
|
||||
this.send({
|
||||
t: GatewayPayloadType.Authenticate,
|
||||
d: {
|
||||
|
@ -98,6 +102,8 @@ export default {
|
|||
break;
|
||||
}
|
||||
case GatewayPayloadType.Ready: {
|
||||
timeline.addCheckpoint("Gateway ready");
|
||||
|
||||
this.user = payload.d.user;
|
||||
this.channels = payload.d.channels;
|
||||
|
||||
|
@ -111,6 +117,7 @@ export default {
|
|||
this.dispatch(payload.t, payload.d);
|
||||
};
|
||||
this.ws.onclose = ({ code }) => {
|
||||
timeline.addCheckpoint("Gateway close");
|
||||
this.authenticated = false;
|
||||
this.user = null;
|
||||
this.channels = null;
|
||||
|
|
|
@ -11,3 +11,11 @@ export default function logger(sink) {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function tableLogger(sink) {
|
||||
return (...args) => {
|
||||
if (getItem(`log:${sink}`)) {
|
||||
console.table(...args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,8 +7,13 @@ import gateway, { GatewayEventType } from './gateway';
|
|||
import { pluginStore } from './stores';
|
||||
|
||||
import "@material-design-icons/font";
|
||||
import { timeline } from './timeline';
|
||||
|
||||
timeline.start();
|
||||
|
||||
function handleGatewaySettlement() {
|
||||
timeline.addCheckpoint("Got gateway settlement");
|
||||
|
||||
const loadingElement = document.getElementById("pre--loading-screen");
|
||||
if (loadingElement) {
|
||||
loadingElement.parentElement.removeChild(loadingElement);
|
||||
|
@ -19,6 +24,8 @@ function handleGatewaySettlement() {
|
|||
});
|
||||
window.__waffle.app = app;
|
||||
|
||||
timeline.addCheckpoint("Created application");
|
||||
|
||||
pluginStore.consumePluginLoaders();
|
||||
const scripts = getItem("app:javascript");
|
||||
scripts.forEach((script) => {
|
||||
|
@ -32,18 +39,24 @@ function handleGatewaySettlement() {
|
|||
document.head.appendChild(style);
|
||||
});
|
||||
|
||||
timeline.addCheckpoint("Loaded custom user content");
|
||||
|
||||
gateway.unsubscribe(GatewayEventType.Ready, handleGatewaySettlement);
|
||||
gateway.unsubscribe(GatewayEventType.Close, handleGatewaySettlement);
|
||||
|
||||
timeline.addCheckpoint("All initialization finished");
|
||||
timeline.dump();
|
||||
}
|
||||
|
||||
function main() {
|
||||
timeline.addCheckpoint("Main reached");
|
||||
useDebuggingApi();
|
||||
useAuthHandlers();
|
||||
initResponsiveHandlers();
|
||||
|
||||
gateway.subscribe(GatewayEventType.Ready, handleGatewaySettlement);
|
||||
gateway.subscribe(GatewayEventType.Close, handleGatewaySettlement);
|
||||
|
||||
|
||||
authWithToken(getItem("auth:token"));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ const defaults = {
|
|||
"log:Gateway": false,
|
||||
"log:Store": false,
|
||||
"log:Messages": false,
|
||||
"log:Timeline": false,
|
||||
"ui:stateful:presistSelectedChannel": true,
|
||||
"ui:showSidebarToggle": false,
|
||||
"ui:alwaysUseMobileChatBar": false,
|
||||
|
|
28
frontend/src/timeline.js
Normal file
28
frontend/src/timeline.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { tableLogger } from "./logging";
|
||||
|
||||
export class Timeline {
|
||||
constructor() {
|
||||
this.startedAt = -1;
|
||||
this.checkpoints = [];
|
||||
this.logger = tableLogger("Timeline");
|
||||
}
|
||||
|
||||
start() {
|
||||
this.startedAt = performance.now();
|
||||
this.checkpoints.push({
|
||||
offset: 0,
|
||||
label: "Timeline Started"
|
||||
});
|
||||
}
|
||||
|
||||
addCheckpoint(label) {
|
||||
const offset = performance.now() - this.startedAt;
|
||||
this.checkpoints.push({ offset, label });
|
||||
}
|
||||
|
||||
dump() {
|
||||
this.logger(this.checkpoints);
|
||||
}
|
||||
}
|
||||
|
||||
export const timeline = new Timeline();
|
Loading…
Reference in a new issue