diff options
author | megumin <megumin.bakaretsurie@gmail.com> | 2022-11-05 10:09:05 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-05 11:09:05 +0100 |
commit | 9663e229a6f4a0126552afb5486cb61d1b7fd8f4 (patch) | |
tree | 4592d1da47da84a74dd544801b515b8b18e23a84 /src/plugins/startupTimings/StartupTimingPage.tsx | |
parent | 0cb24cad7ea6e71e161f0fca36ba38a4049ab59b (diff) | |
download | Vencord-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.tsx | 152 |
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 }}> </div> + {serverTrace && <ServerTrace trace={serverTrace} />} + </React.Fragment> + ); +} + +export default ErrorBoundary.wrap(StartupTimingPage); |