From 8c1979481e6c81d3df0434078f39c16aa41b2c62 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 5 Jul 2024 04:02:34 -0300 Subject: [PATCH] Add patch timings testing to reporter --- scripts/generateReport.ts | 2 +- src/Vencord.ts | 1 + src/debug/Tracer.ts | 52 ++++++++++++++++++++++++++++--------- src/debug/runReporter.ts | 6 +++++ src/webpack/patchWebpack.ts | 13 +++++++--- 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 988f19c5f..b559174d6 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -214,7 +214,7 @@ page.on("console", async e => { switch (tag) { case "WebpackInterceptor:": - const patchFailMatch = message.match(/Patch by (.+?) (had no effect|errored|found no module) \(Module id is (.+?)\): (.+)/)!; + const patchFailMatch = message.match(/Patch by (.+?) (had no effect|errored|found no module|took [\d.]+?ms) \(Module id is (.+?)\): (.+)/)!; if (!patchFailMatch) break; console.error(await getText()); diff --git a/src/Vencord.ts b/src/Vencord.ts index 80aa1f9c7..2615a3373 100644 --- a/src/Vencord.ts +++ b/src/Vencord.ts @@ -23,6 +23,7 @@ export * as Util from "./utils"; export * as QuickCss from "./utils/quickCss"; export * as Updater from "./utils/updater"; export * as Webpack from "./webpack"; +export * as WebpackPatcher from "./webpack/patchWebpack"; export { PlainSettings, Settings }; import "./utils/quickCss"; diff --git a/src/debug/Tracer.ts b/src/debug/Tracer.ts index 7d80f425c..be65cd54b 100644 --- a/src/debug/Tracer.ts +++ b/src/debug/Tracer.ts @@ -23,35 +23,63 @@ if (IS_DEV || IS_REPORTER) { var logger = new Logger("Tracer", "#FFD166"); } -const noop = function () { }; +const Noop = () => { }; -export const beginTrace = !(IS_DEV || IS_REPORTER) ? noop : +export const beginTrace = !(IS_DEV || IS_REPORTER) ? Noop : function beginTrace(name: string, ...args: any[]) { - if (name in traces) + if (name in traces) { throw new Error(`Trace ${name} already exists!`); + } traces[name] = [performance.now(), args]; }; -export const finishTrace = !(IS_DEV || IS_REPORTER) ? noop : function finishTrace(name: string) { - const end = performance.now(); +export const finishTrace = !(IS_DEV || IS_REPORTER) ? () => 0 : + function finishTrace(name: string) { + const end = performance.now(); - const [start, args] = traces[name]; - delete traces[name]; + const [start, args] = traces[name]; + delete traces[name]; - logger.debug(`${name} took ${end - start}ms`, args); -}; + const totalTime = end - start; + logger.debug(`${name} took ${totalTime}ms`, args); + + return totalTime; + }; type Func = (...args: any[]) => any; type TraceNameMapper = (...args: Parameters) => string; -const noopTracer = - (name: string, f: F, mapper?: TraceNameMapper) => f; +function noopTracerWithResults(name: string, f: F, mapper?: TraceNameMapper) { + return function (this: unknown, ...args: Parameters): [ReturnType, number] { + return [f.apply(this, args), 0]; + }; +} + +function noopTracer(name: string, f: F, mapper?: TraceNameMapper) { + return f; +} + +export const traceFunctionWithResults = !(IS_DEV || IS_REPORTER) + ? noopTracerWithResults + : function traceFunctionWithResults(name: string, f: F, mapper?: TraceNameMapper): (this: unknown, ...args: Parameters) => [ReturnType, number] { + return function (this: unknown, ...args: Parameters) { + const traceName = mapper?.(...args) ?? name; + + beginTrace(traceName, ...arguments); + try { + return [f.apply(this, args), finishTrace(traceName)]; + } catch (e) { + finishTrace(traceName); + throw e; + } + }; + }; export const traceFunction = !(IS_DEV || IS_REPORTER) ? noopTracer : function traceFunction(name: string, f: F, mapper?: TraceNameMapper): F { - return function (this: any, ...args: Parameters) { + return function (this: unknown, ...args: Parameters) { const traceName = mapper?.(...args) ?? name; beginTrace(traceName, ...arguments); diff --git a/src/debug/runReporter.ts b/src/debug/runReporter.ts index e0aaf1ff3..9c2684d19 100644 --- a/src/debug/runReporter.ts +++ b/src/debug/runReporter.ts @@ -30,6 +30,12 @@ async function runReporter() { } } + for (const [plugin, moduleId, match, totalTime] of Vencord.WebpackPatcher.patchTimings) { + if (totalTime > 3) { + new Logger("WebpackInterceptor").warn(`Patch by ${plugin} took ${totalTime}ms (Module id is ${String(moduleId)}): ${match}`); + } + } + await Promise.all(Webpack.webpackSearchHistory.map(async ([searchType, args]) => { args = [...args]; diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index afe2abb31..493c09356 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -10,12 +10,14 @@ import { canonicalizeReplacement } from "@utils/patches"; import { PatchReplacement } from "@utils/types"; import { WebpackInstance } from "discord-types/other"; -import { traceFunction } from "../debug/Tracer"; +import { traceFunctionWithResults } from "../debug/Tracer"; import { patches } from "../plugins"; import { _initWebpack, beforeInitListeners, factoryListeners, moduleListeners, waitForSubscriptions, wreq } from "."; const logger = new Logger("WebpackInterceptor", "#8caaee"); +export const patchTimings = [] as Array<[plugin: string, moduleId: PropertyKey, match: string | RegExp, totalTime: number]>; + let webpackChunk: any[]; // Patch the window webpack chunk setter to monkey patch the push method before any chunks are pushed @@ -270,7 +272,7 @@ function patchFactories(factories: Record code.replace(match, replace)); + const executePatch = traceFunctionWithResults(`patch by ${patch.plugin}`, (match: string | RegExp, replace: string) => code.replace(match, replace)); const previousMod = mod; const previousCode = code; @@ -282,7 +284,12 @@ function patchFactories(factories: Record