xref: /expo/packages/@expo/cli/src/utils/profile.ts (revision 8a424beb)
18d307f52SEvan Baconimport chalk from 'chalk';
28d307f52SEvan Bacon
3814b6fafSEvan Baconimport { env } from './env';
4*8a424bebSJames Ideimport * as Log from '../log';
58d307f52SEvan Bacon
68d307f52SEvan Bacon/**
78d307f52SEvan Bacon * Wrap a method and profile the time it takes to execute the method using `EXPO_PROFILE`.
88d307f52SEvan Bacon * Works best with named functions (i.e. not arrow functions).
98d307f52SEvan Bacon *
108d307f52SEvan Bacon * @param fn function to profile.
118d307f52SEvan Bacon * @param functionName optional name of the function to display in the profile output.
128d307f52SEvan Bacon */
138d307f52SEvan Baconexport function profile<IArgs extends any[], T extends (...args: IArgs) => any>(
148d307f52SEvan Bacon  fn: T,
158d307f52SEvan Bacon  functionName: string = fn.name
168d307f52SEvan Bacon): T {
17814b6fafSEvan Bacon  if (!env.EXPO_PROFILE) {
188d307f52SEvan Bacon    return fn;
198d307f52SEvan Bacon  }
208d307f52SEvan Bacon
218d307f52SEvan Bacon  const name = chalk.dim(`⏱  [profile] ${functionName ?? 'unknown'}`);
228d307f52SEvan Bacon
238d307f52SEvan Bacon  return ((...args: IArgs) => {
248d307f52SEvan Bacon    // Start the timer.
258d307f52SEvan Bacon    Log.time(name);
268d307f52SEvan Bacon
278d307f52SEvan Bacon    // Invoke the method.
288d307f52SEvan Bacon    const results = fn(...args);
298d307f52SEvan Bacon
308d307f52SEvan Bacon    // If non-promise then return as-is.
318d307f52SEvan Bacon    if (!(results instanceof Promise)) {
328d307f52SEvan Bacon      Log.timeEnd(name);
338d307f52SEvan Bacon      return results;
348d307f52SEvan Bacon    }
358d307f52SEvan Bacon
368d307f52SEvan Bacon    // Otherwise await to profile after the promise resolves.
378d307f52SEvan Bacon    return new Promise<Awaited<ReturnType<T>>>((resolve, reject) => {
388d307f52SEvan Bacon      results.then(
398d307f52SEvan Bacon        (results) => {
408d307f52SEvan Bacon          resolve(results);
418d307f52SEvan Bacon          Log.timeEnd(name);
428d307f52SEvan Bacon        },
438d307f52SEvan Bacon        (reason) => {
448d307f52SEvan Bacon          reject(reason);
458d307f52SEvan Bacon          Log.timeEnd(name);
468d307f52SEvan Bacon        }
478d307f52SEvan Bacon      );
488d307f52SEvan Bacon    });
498d307f52SEvan Bacon  }) as T;
508d307f52SEvan Bacon}
51