Question
I need to measure how long a function takes to execute in milliseconds.
Originally, this was commonly done with new Date().getTime(), but today the more appropriate standard approach is to use the performance.now() API.
What is the correct way to measure execution time in JavaScript, and when should performance.now() be preferred over older date-based approaches?
Short Answer
By the end of this page, you will understand how to measure execution time in JavaScript, why performance.now() is usually the best choice for benchmarking code, how to use it correctly, and what mistakes to avoid when timing functions.
Concept
Measuring execution time means recording a timestamp before some code runs, recording another timestamp after it finishes, and subtracting the two values.
In JavaScript, the modern tool for this is performance.now().
const start = performance.now();
// code to measure
const end = performance.now();
console.log(`Time taken: ${end - start} ms`);
Why performance.now() matters
performance.now() is designed for performance measurements:
- It returns a time value in milliseconds.
- It has better precision than older date-based methods.
- It is intended for measuring short durations like function execution.
- It is not affected in the same way as wall-clock time APIs used for dates and times.
Older approaches like new Date().getTime() or Date.now() return the current calendar time in milliseconds since the Unix epoch. They are useful for timestamps, but less ideal for precise benchmarking.
What you are really measuring
When you time a function, you are measuring:
- JavaScript execution time
- Possible engine optimizations or warm-up effects
- Time spent in loops, calculations, and synchronous operations
If your function does asynchronous work, such as , , or database calls, you need a different timing pattern because the function may return before the work is finished.
Mental Model
Think of timing code like using a stopwatch.
- Press start right before the function runs.
- Press stop right after it finishes.
- The difference is the duration.
performance.now() is like a stopwatch built specifically for measuring elapsed time.
Date.now() is more like looking at a wall clock. It tells you the current time, which is useful, but it is not the best tool when you care about small, precise durations.
Syntax and Examples
Basic syntax
const start = performance.now();
doSomething();
const end = performance.now();
console.log(`Execution time: ${end - start} ms`);
Example: measuring a synchronous function
function calculateSum() {
let total = 0;
for (let i = 0; i < 1000000; i++) {
total += i;
}
return total;
}
const start = performance.now();
const result = calculateSum();
const end = performance.now();
console.log("Result:", result);
console.log(`Execution time: ${(end - start).toFixed(3)} ms`);
In this example:
startstores the time before the function runs.
Step by Step Execution
Consider this example:
function greetManyTimes() {
let text = "";
for (let i = 0; i < 3; i++) {
text += "Hello ";
}
return text.trim();
}
const start = performance.now();
const message = greetManyTimes();
const end = performance.now();
console.log(message);
console.log(end - start);
Step by step
greetManyTimesis defined.startstores the current high-resolution timestamp.greetManyTimes()runs.- Inside the function:
textstarts as an empty string.- The loop runs 3 times.
- Each time,
"Hello "is added. - The function returns
"Hello Hello Hello".
Real World Use Cases
Measuring execution time is useful in many real programs.
Performance checks
You may want to compare two implementations:
- a
forloop vsArray.map() - two sorting strategies
- a cached function vs a non-cached one
API and async timing
You might measure how long an API request takes:
async function fetchUsers() {
const start = performance.now();
const response = await fetch('/api/users');
const data = await response.json();
const end = performance.now();
console.log(`Request took ${(end - start).toFixed(2)} ms`);
return data;
}
UI performance
In frontend apps, developers measure:
- render time
- event handler duration
- animation performance
- expensive calculations triggered by user input
Backend scripts and tools
Real Codebase Usage
In real projects, developers usually do more than just print a number.
Common patterns
1. Wrap timing in a helper
function measure(label, fn) {
const start = performance.now();
const result = fn();
const end = performance.now();
console.log(`${label}: ${(end - start).toFixed(3)} ms`);
return result;
}
const value = measure("sum calculation", () => {
let total = 0;
for (let i = 0; i < 1000000; i++) total += i;
return total;
});
This keeps timing code reusable.
2. Use try...finally when timing important code
function measureSafe(fn) {
const start = performance.();
{
();
} {
end = performance.();
.();
}
}
Common Mistakes
1. Using Date for precise benchmarking
Broken approach:
const start = new Date().getTime();
doSomething();
const end = new Date().getTime();
This may work, but it is not the preferred modern choice for measuring short durations.
Use instead:
const start = performance.now();
doSomething();
const end = performance.now();
2. Timing async code incorrectly
Broken example:
const start = performance.now();
fetch('/api/data');
const end = performance.now();
console.log(end - start);
This only measures how long it took to start the request, not complete it.
Correct version:
Comparisons
| Approach | Best use | Precision | Good for benchmarking? | Notes |
|---|---|---|---|---|
performance.now() | Measuring elapsed execution time | High | Yes | Preferred modern API |
Date.now() | Current timestamp | Lower | Sometimes | Fine for coarse timing |
new Date().getTime() | Current timestamp | Lower | Sometimes | Older style, same idea as Date.now() |
console.time() / console.timeEnd() | Quick debugging in development |
Cheat Sheet
Quick reference
Preferred timing API
const start = performance.now();
// code here
const end = performance.now();
const duration = end - start;
Older alternatives
Date.now();
new Date().getTime();
Use these for timestamps, not ideal for precise benchmarks.
Async timing
const start = performance.now();
await someAsyncTask();
const end = performance.now();
Quick debug timing
console.time("myTask");
doSomething();
console.timeEnd("myTask");
Good habits
FAQ
Should I use performance.now() or Date.now() in JavaScript?
Use performance.now() for measuring execution time. Use Date.now() for real timestamps such as logging when something happened.
Is new Date().getTime() still valid?
Yes, it still works, but it is an older style. For performance measurement, performance.now() is the better modern choice.
Does performance.now() return milliseconds?
Yes. It returns a time value in milliseconds, typically with fractional precision.
How do I measure an async function's execution time?
Record the start time before the async call and the end time after await completes.
Why do benchmark results change between runs?
Because of factors like JavaScript engine optimization, caching, system load, and background tasks. That is why multiple runs are better than one.
Can I use console.time() instead?
Yes, for quick debugging. But performance.now() is usually better when you want to store or process timing values in your own code.
Mini Project
Description
Build a small timing utility that measures how long different functions take to run. This project demonstrates how to use performance.now() in a reusable way instead of rewriting timing code every time.
Goal
Create a reusable function that measures synchronous and asynchronous tasks and prints their execution times in milliseconds.
Requirements
- Create a function to measure a synchronous callback.
- Create a function to measure an asynchronous callback.
- Display the task name and execution time.
- Test the utility with one CPU-based function and one async function.
Keep learning
Related questions
Adding Table Rows with jQuery: append(), Limits, and Best Practices
Learn how to add table rows in jQuery using append(), what elements are allowed in tables, and safer ways to build rows dynamically.
Bower vs npm: What’s the Difference in JavaScript Package Management?
Learn the plain difference between Bower and npm, how each manages packages, and why npm replaced Bower in most JavaScript projects.
Can `(a == 1 && a == 2 && a == 3)` Ever Be True in JavaScript?
Learn how JavaScript type coercion, loose equality, and custom object conversion can make `a == 1 && a == 2 && a == 3` true.