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();