FrontendAtlas
Interview Questions
Home>JavaScript interview questions> JavaScript coding challenges >Run With a Performance Budget (Sync or Async)

Run With a Performance Budget (Sync or Async)

intermediate
By FrontendAtlas Editorial · Updated Feb 5, 2026
Implement runWithPerfBudget(fn, budgetMs, now?) to time a sync or async function and report whether it stayed within a budget. This mirrors how teams add perf budgets in CI and how you reason about long tasks ("why is this >16ms?") in profiling sessions.

Arguments

  • fn: Function — The operation to run. Can return a value or a Promise.
  • budgetMs: number — Budget in milliseconds (>= 0).
  • now: () => number (optional) — Time source for testability. Defaults to performance.now() when available, else Date.now().

Returns

Promise<{ ok: boolean, durationMs: number, value: any }> — Whether the run stayed within budget, measured duration, and the resolved value.
Examples
await runWithPerfBudget(() => expensiveWork(), 16)
// => { ok: false, durationMs: 42, value: ... }

await runWithPerfBudget(async () => await doFetchLikeWork(), 200)
// => { ok: true, durationMs: 120, value: ... }

Solution

Overview

Measure time before and after running fn. If fn returns a Promise, await it before taking the end timestamp. Use an injectable now() so tests are deterministic.

1

Approach: Monotonic timing + async support

Steps:

1) Validate inputs (fn is function, budgetMs >= 0).

2) Capture start = now().

3) Run fn(). If it returns a promise, await it.

4) Capture end = now().

5) durationMs = max(0, end - start).

6) ok = durationMs <= budgetMs.

Complexity: O(1) overhead.

const defaultNow = () => {
  if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
    return performance.now();
  }
  return Date.now();
};

export default async function runWithPerfBudget(fn, budgetMs, now = defaultNow) {
  if (typeof fn !== 'function') throw new TypeError('fn must be a function');
  if (!Number.isFinite(budgetMs) || budgetMs < 0) throw new TypeError('budgetMs must be a non-negative number');

  const start = now();
  const out = fn();
  const value = out && typeof out.then === 'function' ? await out : out;
  const end = now();

  const durationMs = Math.max(0, end - start);
  return { ok: durationMs <= budgetMs, durationMs, value };
}
export type PerfBudgetResult<T> = {
  ok: boolean;
  durationMs: number;
  value: T;
};

const defaultNow = () => {
  if (typeof performance !== 'undefined' && typeof (performance as any).now === 'function') {
    return (performance as any).now();
  }
  return Date.now();
};

export default async function runWithPerfBudget<T>(
  fn: () => T | Promise<T>,
  budgetMs: number,
  now: () => number = defaultNow
): Promise<PerfBudgetResult<T>> {
  if (typeof fn !== 'function') throw new TypeError('fn must be a function');
  if (!Number.isFinite(budgetMs) || budgetMs < 0) throw new TypeError('budgetMs must be a non-negative number');

  const start = now();
  const out = fn();
  const value = out && typeof (out as any).then === 'function' ? await (out as any) : (out as T);
  const end = now();

  const durationMs = Math.max(0, end - start);
  return { ok: durationMs <= budgetMs, durationMs, value };
}

Notes & Pitfalls

Pitfalls
  • Using Date.now() can jump backwards/forwards if system time changes; prefer performance.now() when available.
  • Measuring tiny operations is noisy; budgets are best for user-visible work (render, parse, large transforms).
  • Optimizing without profiling wastes time; measure first, then fix the biggest bottleneck.
Edge cases
  • budgetMs = 0: ok only when durationMs is 0.
  • fn can be sync or async; treat both the same.
  • If now() is non-monotonic, duration should be clamped to >= 0.
Techniques
  • Inject time source for deterministic tests.
  • Await promise results before final timestamp.
  • Clamp duration to avoid negative values.

Resources

  • MDN – performance.now()

Similar questions

Create a Deferred Promise (For Async Tests)intermediateMeasure Function Duration (Profiling Wrapper)intermediateCleanup Bag (Dispose Subscriptions)easy

Guides

Frontend interview preparation guideGuideFrontend coding interview questions and prep guideBlueprintJavaScript Problems That Actually Show UpBlueprintBuild Great UI in 60 MinutesBlueprint

Preparing for interviews? Use Frontend Coding Challenges first, then move into a concrete Study Plan before targeted Company Prep.

Open frontend interview questionsBrowse JavaScript interview questionsOpen Essential 60Open Machine Coding HubOpen Frontend Coding ChallengesOpen System DesignOpen Interview Prep GuideOpen System Design BlueprintOpen Framework Prep PathsOpen Study PlansOpen JavaScript mastery study planOpen Company PrepOpen JavaScript Framework Prep Guide
↗Incidents hub
27 / 88Next →→