From 1128e8f3ad2587d03b5c24bd69b7e942aa4fb995 Mon Sep 17 00:00:00 2001 From: Rie Takahashi Date: Sun, 17 Sep 2023 19:37:03 +0100 Subject: [PATCH 1/3] feat(startup timings): add Time-To-Interactive info --- .../startupTimings/StartupTimingPage.tsx | 103 +++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/src/plugins/startupTimings/StartupTimingPage.tsx b/src/plugins/startupTimings/StartupTimingPage.tsx index c8cf51da..b6d0d98a 100644 --- a/src/plugins/startupTimings/StartupTimingPage.tsx +++ b/src/plugins/startupTimings/StartupTimingPage.tsx @@ -18,9 +18,27 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; +import { Margins } from "@utils/margins"; +import { classes } from "@utils/misc"; import { findByPropsLazy } from "@webpack"; import { Forms, React } from "@webpack/common"; +interface ITTITrackerEvent { + emoji: string; + name: string; + start: number; + end: number; + hasData(): boolean; +} + +interface ITTITracker { + serializeTTITracker(): Record; + [event: string]: ITTITrackerEvent | string | boolean | null | any; +} + +/** Time-To-Interactive Tracker */ +const TTITracker: ITTITracker = findByPropsLazy("serializeTTITracker"); + interface AppStartPerformance { prefix: string; logs: Log[]; @@ -129,6 +147,78 @@ function ServerTrace({ trace }: ServerTraceProps) { ); } +function TTIAnalytics() { + const analytics = TTITracker.serializeTTITracker(); + const filteredAnalytics = Object.entries(analytics).filter(([key, value]) => !/_start|_end$/.test(key) && value !== null && value !== undefined); + + return ( + + + +
+ {filteredAnalytics.map(([key, value]) => ( + +
{key}
+
{`${value}`}
+
+ ))} +
+
+
+
+ ); +} + +function TTITimings() { + const records: [string, ITTITrackerEvent][] = (Object.entries(TTITracker) as [string, ITTITrackerEvent][]) + .filter(([, value]) => value instanceof Object && value.hasData?.()) as any; + + return ( + + + +
+ Duration + Key + Event + {records.map(([key, event]) => ( + +
{event.end - event.start}ms
+
{key}
+
{event.emoji} {event.name}
+
+ ))} +
+
+
+
+ ); +} + +function UnregisteredTimings() { + const records: [string, ITTITrackerEvent][] = (Object.entries(TTITracker) as [string, ITTITrackerEvent][]) + .filter(([, value]) => value instanceof Object && value.hasData && !value.hasData()) as any; + + return ( + + + +
+ Key + Name + {records.map(([key, event]) => ( + +
{key}
+
{event.emoji} {event.name}
+
+ ))} +
+
+
+
+ ); +} + function StartupTimingPage() { if (!AppStartPerformance?.logs) return
Loading...
; @@ -141,9 +231,18 @@ function StartupTimingPage() { logs={AppStartPerformance.logs} traceEnd={AppStartPerformance.endTime_} /> - {/* Lazy Divider */} -
 
+ + {serverTrace && } + + + + + + + + + ); } From fb7e1c64fd09e4cfdbbd2efb273b1d374bc65a77 Mon Sep 17 00:00:00 2001 From: Rie Takahashi Date: Sun, 17 Sep 2023 19:42:59 +0100 Subject: [PATCH 2/3] fix missing $ in regex --- src/plugins/startupTimings/StartupTimingPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/startupTimings/StartupTimingPage.tsx b/src/plugins/startupTimings/StartupTimingPage.tsx index b6d0d98a..058aba8f 100644 --- a/src/plugins/startupTimings/StartupTimingPage.tsx +++ b/src/plugins/startupTimings/StartupTimingPage.tsx @@ -149,7 +149,7 @@ function ServerTrace({ trace }: ServerTraceProps) { function TTIAnalytics() { const analytics = TTITracker.serializeTTITracker(); - const filteredAnalytics = Object.entries(analytics).filter(([key, value]) => !/_start|_end$/.test(key) && value !== null && value !== undefined); + const filteredAnalytics = Object.entries(analytics).filter(([key, value]) => !/_start$|_end$/.test(key) && value !== null && value !== undefined); return ( From 9bc373d87a99db24ceeb53946efb4883d9548a36 Mon Sep 17 00:00:00 2001 From: Rie Takahashi Date: Sun, 17 Sep 2023 20:45:04 +0100 Subject: [PATCH 3/3] fix: merge tti components, use css file --- .../startupTimings/StartupTimingPage.css | 23 ++++++ .../startupTimings/StartupTimingPage.tsx | 81 ++++++++++--------- 2 files changed, 64 insertions(+), 40 deletions(-) create mode 100644 src/plugins/startupTimings/StartupTimingPage.css diff --git a/src/plugins/startupTimings/StartupTimingPage.css b/src/plugins/startupTimings/StartupTimingPage.css new file mode 100644 index 00000000..ed055142 --- /dev/null +++ b/src/plugins/startupTimings/StartupTimingPage.css @@ -0,0 +1,23 @@ +.vc-startuptimings-server-trace { + color: var(--header-primary); + user-select: text; +} + +.vc-startuptimings-grid { + color: var(--header-primary); + display: grid; + gap: 2px 10px; + user-select: text; +} + +.vc-startuptimings-4-cols { + grid-template-columns: repeat(3, auto) 1fr; +} + +.vc-startuptimings-3-cols { + grid-template-columns: repeat(2, auto) 1fr; +} + +.vc-startuptimings-2-cols { + grid-template-columns: auto 1fr; +} \ No newline at end of file diff --git a/src/plugins/startupTimings/StartupTimingPage.tsx b/src/plugins/startupTimings/StartupTimingPage.tsx index 058aba8f..6670dc9b 100644 --- a/src/plugins/startupTimings/StartupTimingPage.tsx +++ b/src/plugins/startupTimings/StartupTimingPage.tsx @@ -16,6 +16,9 @@ * along with this program. If not, see . */ +import "./StartupTimingPage.css"; + +import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Margins } from "@utils/margins"; @@ -23,6 +26,9 @@ import { classes } from "@utils/misc"; import { findByPropsLazy } from "@webpack"; import { Forms, React } from "@webpack/common"; + +export const cl = classNameFactory("vc-startuptimings-"); + interface ITTITrackerEvent { emoji: string; name: string; @@ -109,11 +115,11 @@ function TimingSection({ title, logs, traceEnd }: TimingSectionProps) { {traceEnd && ( -
+
Trace ended at: {(new Date(traceEnd)).toTimeString()}
)} -
+
Start Interval Delta @@ -137,25 +143,25 @@ function ServerTrace({ trace }: ServerTraceProps) { return ( - + {lines.map(line => ( {line} ))} - + ); } function TTIAnalytics() { const analytics = TTITracker.serializeTTITracker(); - const filteredAnalytics = Object.entries(analytics).filter(([key, value]) => !/_start$|_end$/.test(key) && value !== null && value !== undefined); + const filteredAnalytics = Object.entries(analytics).filter(([key, value]) => value != null && !/_start$|_end$/.test(key)); return ( -
+
{filteredAnalytics.map(([key, value]) => (
{key}
@@ -169,45 +175,26 @@ function TTIAnalytics() { ); } -function TTITimings() { - const records: [string, ITTITrackerEvent][] = (Object.entries(TTITracker) as [string, ITTITrackerEvent][]) - .filter(([, value]) => value instanceof Object && value.hasData?.()) as any; +interface TTITimingsProps { + records: [string, ITTITrackerEvent][]; + title: string; + type: "registered" | "unregistered"; +} + +function TTITimings({ records, title, type }: TTITimingsProps) { + const isRegistered = type === "registered"; return ( - + -
- Duration +
+ {isRegistered && Duration} Key Event {records.map(([key, event]) => ( - -
{event.end - event.start}ms
-
{key}
-
{event.emoji} {event.name}
-
- ))} -
-
- - - ); -} - -function UnregisteredTimings() { - const records: [string, ITTITrackerEvent][] = (Object.entries(TTITracker) as [string, ITTITrackerEvent][]) - .filter(([, value]) => value instanceof Object && value.hasData && !value.hasData()) as any; - - return ( - - - -
- Key - Name - {records.map(([key, event]) => ( - + + {isRegistered &&
{event.end - event.start}ms
}
{key}
{event.emoji} {event.name}
@@ -224,6 +211,12 @@ function StartupTimingPage() { const serverTrace = AppStartPerformance.logGroups.find(g => g.serverTrace)?.serverTrace; + const registeredTTITimings: [string, ITTITrackerEvent][] = (Object.entries(TTITracker)) + .filter(([, value]) => value?.hasData?.()); + + const unregisteredTTITimings: [string, ITTITrackerEvent][] = (Object.entries(TTITracker)) + .filter(([, value]) => value?.hasData && !value.hasData()); + return ( - + - + ); }