C++ Academy · Lesson

Measuring Code Performance

Benchmark with chrono.

Lesson 3 of 413 steps

Measuring Code Performance is a free C++ Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the C++ Academy learning path, and your progress syncs across the web and the CoddyKit app. The C++ Academy course includes 4 lessons in total.

Why Benchmark?

Measuring how long code runs helps you find bottlenecks and verify optimizations. With <chrono> you get portable, type-safe timing.

  • Measure before optimizing.
  • Use a steady clock for reliable intervals.
#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;
    auto start = steady_clock::now();
    auto end = steady_clock::now();
    std::cout << "Timed a block: " << ((end - start).count() >= 0) << '\n';
    return 0;
}

The Basic Pattern

The benchmarking pattern is always the same: capture now() before the work, run it, capture now() after, and subtract.

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;
    auto start = steady_clock::now();
    long sum = 0;
    for (int i = 0; i < 100000; ++i) sum += i;
    auto end = steady_clock::now();
    std::cout << "Sum: " << sum << ", elapsed >= 0: " << ((end - start).count() >= 0) << '\n';
    return 0;
}

Choosing the Unit

Pick the unit that fits the workload. Use microseconds or nanoseconds for fast loops, milliseconds for larger tasks.

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;
    auto start = steady_clock::now();
    long sum = 0;
    for (int i = 0; i < 500000; ++i) sum += i;
    auto end = steady_clock::now();
    auto us = duration_cast<microseconds>(end - start);
    std::cout << "Result: " << sum << ", us non-negative: " << (us.count() >= 0) << '\n';
    return 0;
}

Floating-Point Timing

For human-readable seconds with fractions, use a duration<double> so you keep sub-second precision.

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;
    auto start = steady_clock::now();
    long sum = 0;
    for (int i = 0; i < 200000; ++i) sum += i % 7;
    auto end = steady_clock::now();
    duration<double> secs = end - start;
    std::cout << "Computed " << sum << ", seconds >= 0: " << (secs.count() >= 0) << '\n';
    return 0;
}

A Reusable Timer

Wrap the pattern in a small helper so you can time any callable cleanly and avoid repeating yourself.

#include <iostream>
#include <chrono>

long long timeWork() {
    using namespace std::chrono;
    auto s = steady_clock::now();
    long acc = 0;
    for (int i = 0; i < 100000; ++i) acc += i;
    auto e = steady_clock::now();
    return duration_cast<microseconds>(e - s).count();
}

int main() {
    std::cout << "Microseconds non-negative: " << (timeWork() >= 0) << '\n';
    return 0;
}

Avoid Dead-Code Elimination

Compilers may delete work whose result is unused, ruining benchmarks. Always consume the result, for example by printing it or accumulating into a visible variable.

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;
    auto s = steady_clock::now();
    volatile long sink = 0;
    for (int i = 0; i < 100000; ++i) sink += i;
    auto e = steady_clock::now();
    std::cout << "Sink used: " << (sink > 0) << ", elapsed >= 0: " << ((e - s).count() >= 0) << '\n';
    return 0;
}

Warm-Up Runs

The first run can be slower due to caches and lazy initialization. Do a warm-up pass before measuring for steadier numbers.

#include <iostream>
#include <chrono>

long work() {
    long a = 0;
    for (int i = 0; i < 50000; ++i) a += i;
    return a;
}

int main() {
    using namespace std::chrono;
    work();
    auto s = steady_clock::now();
    long r = work();
    auto e = steady_clock::now();
    std::cout << r << " measured, ok: " << ((e - s).count() >= 0) << '\n';
    return 0;
}

Averaging Multiple Runs

A single measurement is noisy. Run the work many times, sum the elapsed durations, and divide for a stable average.

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;
    long long total = 0;
    const int runs = 5;
    for (int r = 0; r < runs; ++r) {
        auto s = steady_clock::now();
        long acc = 0;
        for (int i = 0; i < 100000; ++i) acc += i;
        auto e = steady_clock::now();
        total += duration_cast<microseconds>(e - s).count();
    }
    std::cout << "Average us non-negative: " << ((total / runs) >= 0) << '\n';
    return 0;
}

Comparing Two Approaches

Benchmarking shines when comparing implementations. Time each one the same way and compare the resulting durations.

#include <iostream>
#include <chrono>
#include <vector>

int main() {
    using namespace std::chrono;
    std::vector<int> v;
    auto s1 = steady_clock::now();
    for (int i = 0; i < 10000; ++i) v.push_back(i);
    auto e1 = steady_clock::now();
    v.clear();
    v.reserve(10000);
    auto s2 = steady_clock::now();
    for (int i = 0; i < 10000; ++i) v.push_back(i);
    auto e2 = steady_clock::now();
    std::cout << "Both timed: " << (((e1 - s1).count() >= 0) && ((e2 - s2).count() >= 0)) << '\n';
    return 0;
}

Beware of Resolution

If the measured work is shorter than the clock's tick, you may read zero. Loop the work enough times to exceed the clock resolution.

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;
    auto s = steady_clock::now();
    int x = 1 + 1;
    auto e = steady_clock::now();
    auto ns = duration_cast<nanoseconds>(e - s).count();
    std::cout << "x=" << x << ", tiny work may read low: " << (ns >= 0) << '\n';
    return 0;
}

Reporting Results

Convert the final duration to a readable unit and print it. Keep the consumed result visible so the optimizer cannot remove the work.

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;
    auto s = steady_clock::now();
    long acc = 0;
    for (int i = 0; i < 300000; ++i) acc += (i * 3) % 11;
    auto e = steady_clock::now();
    auto ms = duration_cast<milliseconds>(e - s).count();
    std::cout << "acc=" << acc << ", ms >= 0: " << (ms >= 0) << '\n';
    return 0;
}

Quick Check

Test your understanding of benchmarking pitfalls.

Recap

You learned how to benchmark code with <chrono>:

  • capture steady_clock::now() before and after, then subtract
  • choose an appropriate unit with duration_cast
  • warm up, average multiple runs, and consume results to defeat dead-code elimination
  • watch out for clock resolution on tiny workloads

Next, you will explore the C++20 calendar and time zone types.

Free to start

Learn C++ with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
51
Lessons
203

Frequently Asked Questions

Is the “Measuring Code Performance” lesson free?

Yes — any 3 lessons of the C++ Academy learning path, including “Measuring Code Performance”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The C++ Academy course includes 4 lessons in total.

What will I learn in “Measuring Code Performance”?

Benchmark with chrono. You practise C++ Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C++ Academy?

No prior experience is required. C++ Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.

How long does the “Measuring Code Performance” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C++ Academy lesson?

Yes. Every C++ Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Durations and Clocks
  2. Time Points
  3. Measuring Code Performance
  4. Calendar and Time Zones
← Back to C++ Academy