Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vite: profiling #8493

Merged
merged 5 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/twenty-pandas-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@remix-run/dev": patch
---

vite: profiling

- build: `--profile`
- dev:
- `--profile` to start with profiler
- `p + enter` to write profile and restart profiler
13 changes: 12 additions & 1 deletion packages/remix-dev/cli/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { transpile as convertFileToJS } from "./useJavascript";
import type { Options } from "../compiler/options";
import { createFileWatchCache } from "../compiler/fileWatchCache";
import { logger } from "../tux";
import * as profiler from "../vite/profiler";

type InitFlags = {
deleteScript?: boolean;
Expand Down Expand Up @@ -143,7 +144,14 @@ export async function viteBuild(
}

let { build } = await import("../vite/build");
await build(root, options);
if (options.profile) {
await profiler.start();
}
try {
await build(root, options);
} finally {
profiler.stop(logger.info);
}
}

export async function watch(
Expand Down Expand Up @@ -191,6 +199,9 @@ export async function dev(

export async function viteDev(root: string, options: ViteDevOptions = {}) {
let { dev } = await import("../vite/dev");
if (options.profile) {
await profiler.start();
}
await dev(root, options);
pcattori marked this conversation as resolved.
Show resolved Hide resolved

// keep `remix vite-dev` alive by waiting indefinitely
Expand Down
1 change: 1 addition & 0 deletions packages/remix-dev/cli/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export async function run(argv: string[] = process.argv.slice(2)) {
"-m": "--mode",
"--open": isBooleanFlag("--open") ? Boolean : String,
"--strictPort": Boolean,
"--profile": Boolean,
}
: {
// Non Vite commands
Expand Down
1 change: 1 addition & 0 deletions packages/remix-dev/vite/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export interface ViteBuildOptions {
logLevel?: Vite.LogLevel;
minify?: Vite.BuildOptions["minify"];
mode?: string;
profile?: boolean;
}

export async function build(
Expand Down
21 changes: 20 additions & 1 deletion packages/remix-dev/vite/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type * as Vite from "vite";
import colors from "picocolors";

import { preloadViteEsm } from "./import-vite-esm-sync";
import * as profiler from "./profiler";

export interface ViteDevOptions {
clearScreen?: boolean;
Expand All @@ -14,6 +15,7 @@ export interface ViteDevOptions {
open?: boolean | string;
port?: number;
strictPort?: boolean;
profile?: boolean;
}

export async function dev(
Expand Down Expand Up @@ -53,5 +55,22 @@ export async function dev(

await server.listen();
server.printUrls();
server.bindCLIShortcuts({ print: true });

let customShortcuts: Vite.CLIShortcut<typeof server>[] = [
{
key: "p",
description: "start/stop the profiler",
async action(server) {
if (profiler.getSession()) {
await profiler.stop(server.config.logger.info);
} else {
await profiler.start(() => {
server.config.logger.info("Profiler started");
});
}
},
},
];

server.bindCLIShortcuts({ print: true, customShortcuts });
}
44 changes: 44 additions & 0 deletions packages/remix-dev/vite/profiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Adapted from:
// - https://github.com/vitejs/vite/blob/9fc5d9cb3a1b9df067e00959faa9da43ae03f776/packages/vite/bin/vite.js
// - https://github.com/vitejs/vite/blob/9fc5d9cb3a1b9df067e00959faa9da43ae03f776/packages/vite/src/node/cli.ts

import fs from "node:fs";
import type { Session } from "node:inspector";
import path from "node:path";
import colors from "picocolors";

declare namespace global {
let __remix_profile_session: Session | undefined;
}

export const getSession = () => global.__remix_profile_session;

export const start = async (callback?: () => void | Promise<void>) => {
let inspector = await import("node:inspector").then((r) => r.default);
let session = (global.__remix_profile_session = new inspector.Session());
session.connect();
session.post("Profiler.enable", () => {
session.post("Profiler.start", callback);
});
};

let profileCount = 0;

export const stop = (log: (message: string) => void): void | Promise<void> => {
let session = getSession();
if (!session) return;
return new Promise((res, rej) => {
session!.post("Profiler.stop", (err, { profile }) => {
if (err) return rej(err);
let outPath = path.resolve(`./remix-${profileCount++}.cpuprofile`);
fs.writeFileSync(outPath, JSON.stringify(profile));
log(
colors.yellow(
`CPU profile written to ${colors.white(colors.dim(outPath))}`
)
);
global.__remix_profile_session = undefined;
res();
});
});
};