[2026] C++ std::chrono::steady_clock | Monotonic time for benchmarks

[2026] C++ std::chrono::steady_clock | Monotonic time for benchmarks

이 글의 핵심

Use steady_clock for elapsed time and timeouts: monotonic guarantees vs system_clock, comparison with high_resolution_clock, benchmarking patterns, and platform notes.

What is steady_clock?

A monotonically non-decreasing clock (C++11). 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.

#include <chrono>
auto start = std::chrono::steady_clock::now();
// work
auto end = std::chrono::steady_clock::now();
auto elapsed = end - start;

Properties

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// Monotonic increase guaranteed
// - Unaffected by system time changes
// - Always moves forward
// - Good for performance measurement
std::chrono::steady_clock::is_steady;  // true

Practical examples

Example 1: Benchmark helper

다음은 cpp를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

template<typename Func>
auto benchmark(Func f) {
    auto start = std::chrono::steady_clock::now();
    
    f();
    
    auto end = std::chrono::steady_clock::now();
    return std::chrono::duration_cast<std::chrono::microseconds>(
        end - start
    );
}
int main() {
    auto duration = benchmark([&] {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    });
    
    std::cout << "Elapsed: " << duration.count() << " μs" << std::endl;
}

Example 2: Timer class

다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

class Timer {
    std::chrono::steady_clock::time_point start;
    
public:
    Timer() : start(std::chrono::steady_clock::now()) {}
    
    void reset() {
        start = std::chrono::steady_clock::now();
    }
    
    auto elapsed() const {
        auto end = std::chrono::steady_clock::now();
        return std::chrono::duration_cast<std::chrono::milliseconds>(
            end - start
        );
    }
};
int main() {
    Timer timer;
    
    std::this_thread::sleep_for(std::chrono::seconds(1));
    
    std::cout << "Elapsed: " << timer.elapsed().count() << " ms" << std::endl;
}

Example 3: Timeout polling

다음은 cpp를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

bool waitWithTimeout(std::chrono::milliseconds timeout) {
    auto start = std::chrono::steady_clock::now();
    
    while (true) {
        if (isReady()) {
            return true;
        }
        
        auto now = std::chrono::steady_clock::now();
        if (now - start >= timeout) {
            return false;  // timeout
        }
        
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

Example 4: Comparing algorithms

아래 코드는 cpp를 사용한 구현 예제입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

void comparePerformance() {
    auto duration1 = benchmark(algorithm1);
    auto duration2 = benchmark(algorithm2);
    
    if (duration1 < duration2) {
        std::cout << "algorithm1 is faster" << std::endl;
    }
    
    auto diff = duration2 - duration1;
    std::cout << "Delta: " << diff.count() << " μs" << std::endl;
}

system_clock vs steady_clock

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// system_clock: wall time (can jump)
auto sys = std::chrono::system_clock::now();
// steady_clock: monotonic
auto steady = std::chrono::steady_clock::now();
// Prefer steady_clock for elapsed intervals

Common pitfalls

Pitfall 1: Wrong clock for intervals

아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// ❌ system_clock (user/NTP can move time backward)
auto start = std::chrono::system_clock::now();
// system time adjusted backward
auto end = std::chrono::system_clock::now();
// duration may be negative
// ✅ steady_clock
auto start = std::chrono::steady_clock::now();
auto end = std::chrono::steady_clock::now();
// non-negative for forward progress

Pitfall 2: Resolution

using period = std::chrono::steady_clock::period;
std::cout << "Resolution: " << period::num << "/" << period::den << " s" << std::endl;

Pitfall 3: Timer call overhead

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

auto start = std::chrono::steady_clock::now();
auto end = std::chrono::steady_clock::now();
auto overhead = end - start;
std::cout << "Overhead: " << overhead.count() << " ns" << std::endl;

Pitfall 4: Very long measurements

다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// For multi-day spans, watch representation limits (rare on desktop)
auto start = std::chrono::steady_clock::now();
// ...
auto end = std::chrono::steady_clock::now();

Usage patterns

아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// 1. Benchmark
auto duration = benchmark(func);
// 2. Timeout
bool success = waitWithTimeout(1000ms);
// 3. Compare algorithms
compareAlgorithms();
// 4. Profiling
profileFunction();

steady_clock vs system_clock vs high_resolution_clock

C++11 chrono offers three clocks you see most often. Picking “high_resolution” by name alone can hurt portability.

ClockMonotonic (is_steady)Meaningful absolute timeTypical use
steady_clockYesEpoch is implementation-defined; not great for “what time is it?”Elapsed time, deadlines, timeouts, benchmarks
system_clockNo (NTP/manual)Wall clock, works with to_time_tLog timestamps, file/DB times, calendar expiry
high_resolution_clockImplementation-definedOften alias of steady or systemShort micro-benchmarks (check is_steady)
Note on high_resolution_clock: The standard allows it to be a typedef of steady_clock or system_clock. For wall time, use system_clock; for elapsed/timeout, use steady_clock directly. Treat high_resolution_clock as a local micro-benchmark helper after you verify behavior.
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;
    std::cout << std::boolalpha;
    std::cout << "steady_clock::is_steady: " << steady_clock::is_steady << '\n';
    std::cout << "system_clock::is_steady: " << system_clock::is_steady << '\n';
    std::cout << "high_resolution_clock::is_steady: " << high_resolution_clock::is_steady << '\n';
}

Measurement patterns

  1. Single interval: auto t0 = steady_clock::now(); … work … auto dt = steady_clock::now() - t0; — keep native duration until you display, then duration_cast to reduce rounding drift.
  2. Accumulating segments: Sum duration values or differences of time_points on the same clock.
  3. Very short work: Two now() calls can already show hundreds of nanoseconds—calibrate or repeat and aggregate (mean/median).
  4. Mixed with sleep: sleep_for only guarantees a minimum sleep; measure real elapsed with steady_clock. 다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
auto t0 = std::chrono::steady_clock::now();
do_work();
auto t1 = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0);

Benchmarking notes

  • Warm up caches and allocators before timing.
  • Repeat runs; use median or mean when noise is high.
  • Prevent optimization of dead work with benchmark helpers (DoNotOptimize) in real harnesses (e.g. Google Benchmark).
  • Clock choice: measure intervals with steady_clock; if you log human-readable timestamps, use system_clock only for that line. The benchmark template above is illustrative; production code should pair micro-benchmarks with profiling tools.

Advanced: timeout with a deadline

For polling loops, a deadline time_point is often clearer than “start + budget” scattered everywhere. 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <chrono>
#include <thread>
// 실행 예제
bool wait_until(std::chrono::steady_clock::time_point deadline,
                auto pred, std::chrono::milliseconds poll) {
    while (std::chrono::steady_clock::now() < deadline) {
        if (pred()) return true;
        std::this_thread::sleep_for(poll);
    }
    return false;
}
  • Prefer condition variables / futures when you can block efficiently instead of polling.
  • If deadline - steady_clock::now() is negative, the deadline already passed—clamp or check before casting.

Platform notes

  • Linux: steady_clock is usually monotonic (CLOCK_MONOTONIC-like). Check period for resolution.
  • Windows: MSVC/MinGW implementations vary but monotonicity is still the contract.
  • macOS/iOS: Typically monotonic; high_resolution_clock often aliases the same underlying clock.
  • Embedded/RTOS: Low tick rates can quantize short intervals—validate period and measurement error.
  • Very long uptime: Theoretical counter overflow is rare on desktop/server duration types. One-line summary: Wall time → system_clock; durations and timeoutssteady_clock; do not pick high_resolution_clock by name alone—check is_steady and your implementation.

FAQ

Q1: What is steady_clock?

A: A clock whose time_points never decrease (for a given process run).

Q2: Difference from system_clock?

A: steady: monotonic. system: tracks system/wall time and can jump.

Q3: Performance measurement?

A: Prefer steady_clock for intervals.

Q4: Precision?

A: Platform-dependent; often nanosecond-class resolution.

Q5: Overhead of now()?

A: Usually small (nanoseconds) but not free for micro-benchmarks.

Q6: Learning resources?

A: C++ Primer, Effective Modern C++, cppreference — steady_clock.

Practical tips

Debugging

  • Fix compiler warnings first.
  • Reproduce with a small test.

Performance

  • Profile before optimizing.
  • Define measurable targets.

Code review

  • Follow team conventions.

Production checklist

Before coding

  • Right approach?
  • Maintainable?
  • Meets performance needs?

While coding

  • Warnings cleared?
  • Edge cases covered?
  • Error handling OK?

At review

  • Intent clear?
  • Tests sufficient?
  • Documented?

Keywords

C++, steady_clock, chrono, benchmark, C++11

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3