From 17e086769d4fec2525c2b207c94fa5299ccb936c Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Thu, 17 Nov 2022 21:11:32 +0200 Subject: [PATCH] add "timeline" system for measuring app start performance --- frontend/src/auth.js | 2 ++ frontend/src/components/Main.svelte | 10 ++++++++++ frontend/src/debuggingapi.js | 2 ++ frontend/src/gateway.js | 7 +++++++ frontend/src/logging.js | 8 ++++++++ frontend/src/main.js | 15 ++++++++++++++- frontend/src/storage.js | 1 + frontend/src/timeline.js | 28 ++++++++++++++++++++++++++++ 8 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 frontend/src/timeline.js diff --git a/frontend/src/auth.js b/frontend/src/auth.js index 9e53d79..1ba9ad3 100644 --- a/frontend/src/auth.js +++ b/frontend/src/auth.js @@ -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); diff --git a/frontend/src/components/Main.svelte b/frontend/src/components/Main.svelte index 9749554..b82a4c6 100644 --- a/frontend/src/components/Main.svelte +++ b/frontend/src/components/Main.svelte @@ -1,9 +1,19 @@ diff --git a/frontend/src/debuggingapi.js b/frontend/src/debuggingapi.js index a8c0d43..2a0fcc1 100644 --- a/frontend/src/debuggingapi.js +++ b/frontend/src/debuggingapi.js @@ -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 }; diff --git a/frontend/src/gateway.js b/frontend/src/gateway.js index 0615b52..96a471f 100644 --- a/frontend/src/gateway.js +++ b/frontend/src/gateway.js @@ -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; diff --git a/frontend/src/logging.js b/frontend/src/logging.js index 31cc107..199730c 100644 --- a/frontend/src/logging.js +++ b/frontend/src/logging.js @@ -11,3 +11,11 @@ export default function logger(sink) { } }; } + +export function tableLogger(sink) { + return (...args) => { + if (getItem(`log:${sink}`)) { + console.table(...args); + } + }; +} diff --git a/frontend/src/main.js b/frontend/src/main.js index 4ffbccb..f61908b 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -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")); } diff --git a/frontend/src/storage.js b/frontend/src/storage.js index 6ca2973..43d795b 100644 --- a/frontend/src/storage.js +++ b/frontend/src/storage.js @@ -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, diff --git a/frontend/src/timeline.js b/frontend/src/timeline.js new file mode 100644 index 0000000..11bb2cf --- /dev/null +++ b/frontend/src/timeline.js @@ -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();