Question
I want to measure how long parts of my C program take to run.
I first tried using time() like this:
printf("**MyProgram::before time= %ld\n", time(NULL));
doSomething();
doSomethingLong();
printf("**MyProgram::after time= %ld\n", time(NULL));
What I do not understand is why the before and after values are sometimes the same.
I know this is not full profiling. I just want to measure elapsed time for a piece of code.
I also tried this approach:
struct timeval diff, startTV, endTV;
gettimeofday(&startTV, NULL);
doSomething();
doSomethingLong();
gettimeofday(&endTV, NULL);
timersub(&endTV, &startTV, &diff);
printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);
How should I interpret output like these?
time taken = 0 26339time taken = 4 45025
Does 0 26339 mean 26,339 nanoseconds, or 26.339 milliseconds?
Does 4 45025 mean 4 seconds and 25 milliseconds, or something else?
Short Answer
By the end of this page, you will understand why time() often shows the same value before and after fast code, how gettimeofday() measures shorter durations, and how to correctly read tv_sec and tv_usec in C. You will also see safer modern alternatives and practical examples for timing code.
Concept
time() and gettimeofday() both deal with time, but they are used at different levels of precision.
time() returns the current calendar time in whole seconds since the Unix epoch. That means it has 1-second resolution. If your code finishes in less than one second, the value before and after may be identical.
For example, if both calls happen during the same second:
time_t a = time(NULL);
/* code runs quickly */
time_t b = time(NULL);
a and b can be equal even though time did pass.
gettimeofday() gives you a struct timeval, which contains:
tv_sec: whole secondstv_usec: microseconds
A microsecond is 1/1,000,000 of a second.
So this structure lets you measure much smaller intervals than time().
Example:
gettimeofday(&tv, );
Mental Model
Think of time() as a wall clock that only shows hours, minutes, and seconds, but no fractions of a second. If you look at it twice very quickly, it may show the same second both times.
Think of gettimeofday() as a stopwatch that shows:
- seconds
- tiny fractions of a second
So if time() is like saying, "The race started at 10:15:03 and ended at 10:15:03," gettimeofday() is like saying, "It took 0.026339 seconds."
Another way to picture struct timeval:
tv_sec= the big unit buckettv_usec= the leftover small-unit bucket
Together they describe one elapsed duration.
So 4 45025 is not two unrelated numbers. It means:
- 4 full seconds
- plus 45,025 microseconds
- total: 4.045025 seconds
Syntax and Examples
The basic syntax with gettimeofday() looks like this:
#include <stdio.h>
#include <sys/time.h>
int main(void) {
struct timeval start, end, diff;
gettimeofday(&start, NULL);
/* code to measure */
gettimeofday(&end, NULL);
timersub(&end, &start, &diff);
printf("Elapsed: %ld.%06ld seconds\n", diff.tv_sec, diff.tv_usec);
return 0;
}
What the fields mean
diff.tv_secis the number of whole secondsdiff.tv_usecis the remaining microseconds%06ldprints microseconds with leading zeros so the decimal-style output looks correct
Example with a delay
#include <stdio.h>
{
gettimeofday(&start, );
usleep();
gettimeofday(&end, );
timersub(&end, &start, &diff);
(, diff.tv_sec, diff.tv_usec);
(, diff.tv_sec, diff.tv_usec);
;
}
Step by Step Execution
Consider this example:
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
int main(void) {
struct timeval start, end, diff;
gettimeofday(&start, NULL);
usleep(45025);
gettimeofday(&end, NULL);
timersub(&end, &start, &diff);
printf("%ld %ld\n", diff.tv_sec, diff.tv_usec);
return 0;
}
Step by step
-
gettimeofday(&start, NULL);- The current time is stored in
start. - Example:
start.tv_sec = 100start.tv_usec = 200000
- The current time is stored in
-
usleep(45025);
Real World Use Cases
Measuring elapsed time is common in many kinds of C programs.
1. Benchmarking a function
You may want to compare two implementations of the same algorithm.
gettimeofday(&start, NULL);
sort_data(items, count);
gettimeofday(&end, NULL);
2. Measuring file I/O
You can check how long it takes to read or write a large file.
- loading logs
- parsing CSV data
- saving reports
3. Monitoring network calls
If your program talks to a server, timing helps identify slow requests.
- DNS lookup
- socket connect
- data receive
4. Checking startup performance
Developers often time stages such as:
- reading configuration
- initializing libraries
- connecting to databases
5. Debugging user complaints
If users say a feature is slow, small timing logs can reveal where time is spent.
Example:
printf("Loading config...\n");
gettimeofday(&start, NULL);
load_config();
gettimeofday(&end, NULL);
6. Batch and data-processing scripts
For scripts that process many records, it helps to know:
Real Codebase Usage
In real projects, developers usually do more than print two timestamps.
Common patterns
Guard timing around specific blocks
gettimeofday(&start, NULL);
if (load_data() != 0) {
return 1;
}
gettimeofday(&end, NULL);
This isolates the time for one operation.
Log both total time and stage time
Large programs often measure phases separately:
- initialization
- processing
- cleanup
Wrap timing in helper functions or macros
Instead of repeating timing code everywhere, teams often create utilities.
double elapsed_ms(struct timeval start, struct timeval end) {
return (end.tv_sec - start.tv_sec) * 1000.0 +
(end.tv_usec - start.tv_usec) / 1000.0;
}
Use early returns carefully
If your function has multiple exits, make sure timing still gets recorded when needed.
Prefer monotonic clocks for elapsed time
In production code, clock_gettime(CLOCK_MONOTONIC, ...) is often better than because it is not affected by wall-clock adjustments.
Common Mistakes
1. Confusing microseconds with nanoseconds
tv_usec means microseconds, not nanoseconds.
Broken interpretation:
/* Wrong idea: 26339 means nanoseconds */
Correct interpretation:
26339 usec=26.339 ms
2. Expecting time() to measure fast code
time() only has second-level resolution.
Broken expectation:
printf("%ld\n", time(NULL));
fast_function();
printf("%ld\n", time(NULL));
If fast_function() takes under one second, both values may match.
3. Printing elapsed time in a confusing format
This output:
printf("%ld %ld\n", diff.tv_sec, diff.tv_usec);
is technically correct, but easy to misread.
Comparisons
| Method | Resolution | Good for | Limitation |
|---|---|---|---|
time() | Seconds | Logging wall time, coarse timestamps | Too coarse for fast operations |
gettimeofday() | Microseconds | Simple elapsed timing, debugging | Affected by system clock changes |
clock() | CPU time ticks | Measuring CPU time used by the process | Not the same as real elapsed time |
clock_gettime(CLOCK_MONOTONIC) | Usually very fine | Best choice for elapsed timing on POSIX | Slightly more setup |
time() vs gettimeofday()
Cheat Sheet
time(NULL)returns current time in seconds.- Fast code may show the same
time()value before and after. gettimeofday()fills astruct timeval.tv_sec= secondstv_usec= microseconds1 ms = 1000 usec1 usec = 1000 ns
Read these results
0 26339=0 seconds + 26339 microseconds0 26339=26.339 ms4 45025=4 seconds + 45025 microseconds4 45025=4.045025 s
Typical timing pattern
struct timeval start, , ;
gettimeofday(&start, );
gettimeofday(&end, );
timersub(&end, &start, &diff);
(, diff.tv_sec, diff.tv_usec);
FAQ
Why are time() values before and after my function the same?
Because time() only measures whole seconds. If your code runs in less than one second, both calls can return the same value.
Does tv_usec mean nanoseconds?
No. tv_usec means microseconds.
How many milliseconds is 26339 microseconds?
26339 microseconds is 26.339 milliseconds.
What does 4 45025 mean in struct timeval output?
It means 4 seconds and 45,025 microseconds, which is 4.045025 seconds total.
Is gettimeofday() good for benchmarking?
It is good for simple measurements, but for more reliable elapsed timing, clock_gettime(CLOCK_MONOTONIC, ...) is usually better.
Should I print tv_sec and tv_usec separately?
Mini Project
Description
Build a small C program that times several tasks and prints the elapsed duration in both microseconds and milliseconds. This demonstrates how to measure code execution more clearly than using time() alone.
Goal
Create a timing utility that measures short operations and prints human-readable elapsed times.
Requirements
- Use
gettimeofday()to capture a start and end time. - Measure at least two separate operations.
- Print the elapsed result as seconds, microseconds, and milliseconds.
- Format microseconds correctly using zero padding.
- Include one short operation and one longer operation for comparison.
Keep learning
Related questions
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
C Pointer to Array vs Array of Pointers: How to Read Complex Declarations
Learn the difference between pointer-to-array and array-of-pointers in C, plus a simple rule for reading complex declarations correctly.