aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/startupTimings/StartupTimingPage.tsx
diff options
context:
space:
mode:
authormegumin <megumin.bakaretsurie@gmail.com>2022-11-05 10:09:05 +0000
committerGitHub <noreply@github.com>2022-11-05 11:09:05 +0100
commit9663e229a6f4a0126552afb5486cb61d1b7fd8f4 (patch)
tree4592d1da47da84a74dd544801b515b8b18e23a84 /src/plugins/startupTimings/StartupTimingPage.tsx
parent0cb24cad7ea6e71e161f0fca36ba38a4049ab59b (diff)
downloadVencord-9663e229a6f4a0126552afb5486cb61d1b7fd8f4.tar.gz
Vencord-9663e229a6f4a0126552afb5486cb61d1b7fd8f4.tar.bz2
Vencord-9663e229a6f4a0126552afb5486cb61d1b7fd8f4.zip
feat(plugins): add Startup Timings (#189)
Diffstat (limited to 'src/plugins/startupTimings/StartupTimingPage.tsx')
-rw-r--r--src/plugins/startupTimings/StartupTimingPage.tsx152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/plugins/startupTimings/StartupTimingPage.tsx b/src/plugins/startupTimings/StartupTimingPage.tsx
new file mode 100644
index 0000000..f864138
--- /dev/null
+++ b/src/plugins/startupTimings/StartupTimingPage.tsx
@@ -0,0 +1,152 @@
+/*
+ * Vencord, a modification for Discord's desktop app
+ * Copyright (c) 2022 Vendicated and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+import ErrorBoundary from "../../components/ErrorBoundary";
+import { Flex } from "../../components/Flex";
+import { lazyWebpack } from "../../utils";
+import { filters } from "../../webpack";
+import { Forms, React } from "../../webpack/common";
+
+interface AppStartPerformance {
+ prefix: string;
+ logs: Log[];
+ logGroups: LogGroup[];
+ endTime_: number;
+ isTracing_: boolean;
+}
+
+interface LogGroup {
+ index: number;
+ timestamp: number;
+ logs: Log[];
+ nativeLogs: any[];
+ serverTrace: string;
+}
+
+interface Log {
+ emoji: string;
+ prefix: string;
+ log: string;
+ timestamp?: number;
+ delta?: number;
+}
+
+const AppStartPerformance = lazyWebpack(filters.byProps("markWithDelta", "markAndLog", "markAt")) as AppStartPerformance;
+
+interface TimerItemProps extends Log {
+ instance: {
+ sinceStart: number;
+ sinceLast: number;
+ };
+}
+
+function TimerItem({ emoji, prefix, log, delta, instance }: TimerItemProps) {
+ return (
+ <React.Fragment>
+ <span>{instance.sinceStart.toFixed(3)}s</span>
+ <span>{instance.sinceLast.toFixed(3)}s</span>
+ <span>{delta?.toFixed(0) ?? ""}</span>
+ <span><pre>{emoji} {prefix ?? " "}{log}</pre></span>
+ </React.Fragment>
+ );
+}
+
+interface TimingSectionProps {
+ title: string;
+ logs: Log[];
+ traceEnd?: number;
+}
+
+function TimingSection({ title, logs, traceEnd }: TimingSectionProps) {
+ const startTime = logs.find(l => l.timestamp)?.timestamp ?? 0;
+
+ let lastTimestamp = startTime;
+ const timings = logs.map(log => {
+ // Get last log entry with valid timestamp
+ const timestamp = log.timestamp ?? lastTimestamp;
+
+ const sinceStart = (timestamp - startTime) / 1000;
+ const sinceLast = (timestamp - lastTimestamp) / 1000;
+
+ lastTimestamp = timestamp;
+
+ return { sinceStart, sinceLast };
+ });
+
+ return (
+ <Forms.FormSection title={title} tag={Forms.FormTitle.Tags.H1}>
+ <code>
+ {traceEnd && (
+ <div style={{ color: "var(--header-primary)", marginBottom: 5, userSelect: "text" }}>
+ Trace ended at: {(new Date(traceEnd)).toTimeString()}
+ </div>
+ )}
+ <div style={{ color: "var(--header-primary)", display: "grid", gridTemplateColumns: "repeat(3, auto) 1fr", gap: "2px 10px", userSelect: "text" }}>
+ <span>Start</span>
+ <span>Interval</span>
+ <span>Delta</span>
+ <span style={{ marginBottom: 5 }}>Event</span>
+ {AppStartPerformance.logs.map((log, i) => (
+ <TimerItem key={i} {...log} instance={timings[i]} />
+ ))}
+ </div>
+ </code>
+ </Forms.FormSection>
+ );
+}
+
+interface ServerTraceProps {
+ trace: string;
+}
+
+function ServerTrace({ trace }: ServerTraceProps) {
+ const lines = trace.split("\n");
+
+ return (
+ <Forms.FormSection title="Server Trace" tag={Forms.FormTitle.Tags.H2}>
+ <code>
+ <Flex flexDirection="column" style={{ color: "var(--header-primary)", gap: 5, userSelect: "text" }}>
+ {lines.map(line => (
+ <span>{line}</span>
+ ))}
+ </Flex>
+ </code>
+ </Forms.FormSection>
+ );
+}
+
+function StartupTimingPage() {
+ if (!AppStartPerformance?.logs) return <div>Loading...</div>;
+
+ const serverTrace = AppStartPerformance.logGroups.find(g => g.serverTrace)?.serverTrace;
+
+ return (
+ <React.Fragment>
+ <TimingSection
+ title="Startup Timings"
+ logs={AppStartPerformance.logs}
+ traceEnd={AppStartPerformance.endTime_}
+ />
+ {/* Lazy Divider */}
+ <div style={{ marginTop: 5 }}>&nbsp;</div>
+ {serverTrace && <ServerTrace trace={serverTrace} />}
+ </React.Fragment>
+ );
+}
+
+export default ErrorBoundary.wrap(StartupTimingPage);