본문으로 건너뛰기 C++ std::chrono Guide — duration, time_point, Clocks &

C++ std::chrono Guide — duration, time_point, Clocks &

C++ std::chrono Guide — duration, time_point, Clocks &

이 글의 핵심

Measure time correctly with std::chrono: duration and time_point, choosing clocks, duration_cast, benchmarks, timeouts, timestamps, and production patterns.

Introduction: “My benchmark numbers change every run”

I used time() and the results are not trustworthy

You wrote benchmark code. You measured a function with time() or clock(), but results swing wildly between runs. The system clock may be stepped by NTP, and clock() measures CPU time, which is misleading when threads or sleep are involved.

Problematic code:

// ❌ Bad: time() is second resolution — cannot measure sub-second work
#include <ctime>
void benchmark() {
    time_t start = time(nullptr);
    doSomething();
    time_t end = time(nullptr);
    printf("Elapsed: %ld sec\n", end - start);  // stays 0 if under 1 second
}
// ❌ Bad: clock() is CPU time — does not advance during sleep
#include <ctime>
void benchmark() {
    clock_t start = clock();
    doSomething();  // inaccurate if it includes sleep
    clock_t end = clock();
    printf("CPU: %f sec\n", (double)(end - start) / CLOCKS_PER_SEC);
}

Fix with chrono:

// ✅ Good: steady_clock is monotonic, nanosecond-capable resolution
#include <chrono>
#include <iostream>
void benchmark() {
    auto start = std::chrono::steady_clock::now();
    doSomething();
    auto end = std::chrono::steady_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    std::cout << "Elapsed: " << elapsed.count() << " ms\n";
}

After reading this article you will:

  • Understand std::chrono duration, time_point, and clocks
  • Convert units with duration_cast
  • Apply patterns for benchmarks, timeouts, and log timestamps
  • Recognize common mistakes and production-safe habits

Analogy: one toolbox convention

Time, files, logs, and JSON are wrenches you reach for often. Pick one standard library and one convention, and the whole team shares units and formats.


Practical note: This article is grounded in real issues seen in large C++ codebases, including pitfalls that textbooks rarely emphasize.

Table of contents

  1. Real-world problem scenarios
  2. duration: a length of time
  3. time_point: an instant
  4. Clocks: system_clock, steady_clock, high_resolution_clock
  5. duration_cast and unit conversion
  6. C++20 calendar and date arithmetic
  7. Hands-on timing examples
  8. Common errors and fixes
  9. Best practices
  10. Production patterns
  11. Checklist
  12. Summary

1. Real-world problem scenarios

Scenario 1: Benchmarks always look different

Problem: Comparing algorithms A and B with time(nullptr) prints 0 seconds for both when work finishes in under a second.

// ❌ Problem: sub-second runs always show 0
time_t t1 = time(nullptr);
algorithmA();
time_t t2 = time(nullptr);
printf("A: %ld sec\n", t2 - t1);  // even 50 ms of work prints 0

Fix: Use std::chrono::steady_clock and duration_cast for millisecond or microsecond resolution.

// ✅ Fix
#include <chrono>
auto start = std::chrono::steady_clock::now();
algorithmA();
auto end = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "A: " << ms.count() << " ms\n";

Scenario 2: Timeout math breaks when NTP adjusts the clock

Problem: You implement “timeout after 30 seconds” with system_clock::now() + 30s. If NTP steps the system clock backward, your deadline can end up in the past relative to a buggy loop condition, or logic can stall unexpectedly.

// ❌ Problem: system_clock follows the system wall clock
auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(30);
while (std::chrono::system_clock::now() < deadline) {
    doWork();  // clock steps can make comparisons misleading for elapsed-time semantics
}

Fix: For elapsed time and timeouts, use steady_clock. It is monotonic and not affected by NTP.

// ✅ Fix
auto start = std::chrono::steady_clock::now();
auto timeout = std::chrono::seconds(30);
while (std::chrono::steady_clock::now() - start < timeout) {
    doWork();
}

Scenario 3: Human-readable timestamps in logs

Problem: steady_clock::now() is an implementation-defined epoch (often “since boot”). It is not a calendar time. For "2026-03-11 14:30:00" you need system_clock (and formatting).

// ❌ steady_clock is not a calendar instant
auto tp = std::chrono::steady_clock::now();
// Not directly convertible to local calendar time

// ✅ system_clock corresponds to Unix-style wall time
auto tp = std::chrono::system_clock::now();
// C++20 chrono formatting or C localtime/strftime can format it

Scenario 4: Different duration types — compile errors

Problem: Mixing units without care can be confusing; casting to a coarser unit needs duration_cast.

// Different duration types — often need explicit casts for a specific unit
auto s = std::chrono::seconds(1);
auto ms = std::chrono::milliseconds(500);
auto sum = s + ms;  // ✅ C++11+ usually promotes to a common duration type
// When you need a specific unit, use duration_cast

Scenario 5: Asio timers expect chrono durations

Problem: APIs like Boost.Asio expect a chrono::duration, not a bare int.

// ❌ Ambiguous
timer.expires_after(30);  // 30 what?

// ✅ Clear
timer.expires_after(std::chrono::seconds(30));

Scenario 6: “Next Monday” style date math is painful in C

Problem: With localtime and struct tm, month boundaries and leap years are easy to get wrong.

// ❌ C++17 and below: manual date math is error-prone
std::tm tm = *std::localtime(&tt);
tm.tm_mday += 7;  // crosses month?
mktime(&tm);      // normalization required

Fix: C++20 std::chrono calendar types (year_month_day, weekday, …) model dates more safely.

// ✅ C++20: calendar types
#include <chrono>
using namespace std::chrono;
auto today = floor<days>(system_clock::now());
year_month_day ymd = year_month_day{sys_days{today}};
// Use weekday_indexed / calendar algorithms for “next Monday”, etc.

2. duration: a length of time

Basics

std::chrono::duration represents a length of time. It is a template over a representation type (Rep) and a period (Period) as a std::ratio.

// After paste: g++ -std=c++17 -o duration_basic duration_basic.cpp && ./duration_basic
#include <chrono>
#include <iostream>
int main() {
    std::chrono::nanoseconds  ns(1000000000);   // 10^9 ns = 1 s
    std::chrono::microseconds us(1000000);       // 10^6 µs = 1 s
    std::chrono::milliseconds ms(1000);         // 1000 ms = 1 s
    std::chrono::seconds      s(1);              // 1 s
    std::chrono::minutes      m(1);              // 1 min
    std::chrono::hours        h(1);              // 1 h
    std::cout << "1 s = " << ns.count() << " ns\n";
    std::cout << "1 s = " << ms.count() << " ms\n";
    std::cout << "1 min = " << std::chrono::duration_cast<std::chrono::seconds>(m).count() << " s\n";
    auto sum = std::chrono::seconds(30) + std::chrono::milliseconds(500);
    std::cout << "30.5 s = " << std::chrono::duration_cast<std::chrono::milliseconds>(sum).count() << " ms\n";
    return 0;
}

Sample output:

1 s = 1000000000 ns
1 s = 1000 ms
1 min = 60 s
30.5 s = 30500 ms

Internals:

  • Rep: e.g. int64_t, double — stores the numeric value
  • Period: e.g. std::milli — tick size as a std::ratio

duration arithmetic

#include <chrono>
int main() {
    using namespace std::chrono;
    auto d1 = seconds(10);
    auto d2 = milliseconds(500);
    auto sum = d1 + d2;
    auto diff = d1 - d2;
    auto doubled = d1 * 2;
    auto half = d1 / 2;
    bool b = (d1 > d2);
    auto ms = duration_cast<milliseconds>(sum);
    std::cout << ms.count() << " ms\n";
    return 0;
}

Custom durations

#include <chrono>
#include <iostream>
using Deciseconds = std::chrono::duration<int, std::ratio<1, 10>>;          // 0.1 s
using FrameDuration = std::chrono::duration<double, std::ratio<1, 30>>;     // 1/30 s per frame
int main() {
    Deciseconds ds(5);    // 0.5 s
    FrameDuration fd(1);  // one 1/30 s frame
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(ds);
    std::cout << "5 deciseconds = " << ms.count() << " ms\n";
    return 0;
}

3. time_point: an instant

Basics

std::chrono::time_point is an instant: “how far after this clock’s epoch,” stored as a duration.

// After paste: g++ -std=c++17 -o timepoint_basic timepoint_basic.cpp && ./timepoint_basic
#include <chrono>
#include <iostream>
int main() {
    auto now_sys = std::chrono::system_clock::now();
    auto now_steady = std::chrono::steady_clock::now();
    auto future = now_sys + std::chrono::hours(24);
    auto past = now_sys - std::chrono::seconds(3600);
    auto elapsed = now_steady - (now_steady - std::chrono::milliseconds(100));
    std::cout << "Elapsed: " << elapsed.count() << " (steady_clock tick units)\n";
    auto tt = std::chrono::system_clock::to_time_t(now_sys);
    std::cout << "time_t: " << tt << "\n";
    return 0;
}

time_point operations

#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;
    auto tp = steady_clock::now();
    auto later = tp + seconds(10);
    auto earlier = tp - milliseconds(500);
    auto diff = later - tp;
    auto ms = duration_cast<milliseconds>(diff);
    std::cout << ms.count() << " ms\n";
    return 0;
}

4. Clocks: system_clock, steady_clock, high_resolution_clock

The three standard clocks

flowchart TB
    subgraph system[system_clock]
        S1[Wall calendar time]
        S2[Can be adjusted by NTP]
        S3[to_time_t available]
    end
    subgraph steady[steady_clock]
        T1[Monotonic]
        T2[Not affected by NTP steps]
        T3[Benchmarks and timeouts]
    end
    subgraph high[high_resolution_clock]
        H1[Highest available resolution]
        H2[May alias steady on some implementations]
    end
ClockTypical useNTP / wall clock stepsMonotonic
system_clockReal date/time, log timestampsYesNo
steady_clockBenchmarks, timeouts, elapsed timeNoYes
high_resolution_clockWhen you need finest resolutionImplementation-definedImplementation-defined

system_clock

#include <chrono>
#include <ctime>
#include <iostream>
int main() {
    auto now = std::chrono::system_clock::now();
    auto tt = std::chrono::system_clock::to_time_t(now);
    std::tm* tm = std::localtime(&tt);
    char buf[64];
    std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
    std::cout << "Now: " << buf << "\n";
    auto tp = std::chrono::system_clock::from_time_t(tt);
    return 0;
}

steady_clock

#include <chrono>
#include <iostream>
#include <thread>
int main() {
    auto start = std::chrono::steady_clock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    auto end = std::chrono::steady_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    std::cout << "Slept: " << elapsed.count() << " ms\n";
    // steady_clock has no to_time_t — not a calendar clock
    return 0;
}

high_resolution_clock

#include <chrono>
#include <iostream>
int main() {
    // libstdc++/libc++: often an alias of steady_clock
    // MSVC: may differ
    auto start = std::chrono::high_resolution_clock::now();
    volatile int x = 0;
    for (int i = 0; i < 1000; ++i) x += i;
    auto end = std::chrono::high_resolution_clock::now();
    auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
    std::cout << "Loop: " << ns.count() << " ns\n";
    return 0;
}

Note: If monotonicity matters, prefer steady_clock; high_resolution_clock is not guaranteed to be steady.


5. duration_cast and unit conversion

duration_cast

Use duration_cast to convert between duration units. Truncation toward zero is typical when converting to a coarser unit.

#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;
    milliseconds ms(1500);
    seconds s = duration_cast<seconds>(ms);
    std::cout << "1500 ms = " << s.count() << " s (truncated)\n";
    duration<double> sec(1.5);
    auto ms2 = duration_cast<milliseconds>(sec);
    std::cout << "1.5 s = " << ms2.count() << " ms\n";
    auto sec_floor = floor<seconds>(ms);
    auto sec_ceil = ceil<seconds>(ms);
    auto sec_round = round<seconds>(ms);
    std::cout << "floor: " << sec_floor.count() << ", ceil: " << sec_ceil.count()
              << ", round: " << sec_round.count() << "\n";
    return 0;
}

floor, ceil, round (C++17)

#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;
    milliseconds ms(1250);
    auto s_floor = floor<seconds>(ms);
    auto s_ceil = ceil<seconds>(ms);
    auto s_round = round<seconds>(ms);
    std::cout << "1250 ms -> floor: " << s_floor.count()
              << " s, ceil: " << s_ceil.count()
              << " s, round: " << s_round.count() << " s\n";
    return 0;
}

6. C++20 calendar and date arithmetic

C++20 extends <chrono> with calendar and timezone facilities. Types like year, month, day, weekday, and year_month_day make many date operations type-safe.

year_month_day

#include <chrono>
#include <iostream>
#if __cplusplus >= 202002L
int main() {
    using namespace std::chrono;
    year_month_day ymd{year(2026), month(3), day(11)};
    if (ymd.ok()) {
        std::cout << "Valid date: " << ymd << "\n";
    }
    auto tp = sys_days{ymd};
    auto ymd2 = year_month_day{floor<days>(tp)};
    auto today = year_month_day{floor<days>(system_clock::now())};
    std::cout << "Today: " << today << "\n";
    return 0;
}
#endif

weekday, month_day_last

#if __cplusplus >= 202002L
#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;
    year_month_day ymd{2026y, March, 11d};
    std::cout << "2026-03-11: " << weekday{ymd} << "\n";
    year_month_day_last ymdl{year(2026), month_day_last(month(2))};
    std::cout << "Last of 2026-02: " << year_month_day{ymdl} << "\n";
    return 0;
}
#endif

C++20 chrono vs C++17 and earlier

FeatureC++17 and earlierC++20
Date representationtime_t + tmyear_month_day, etc.
Weekdaytm.tm_wdayweekday
Last day of monthmanualmonth_day_last
Formattingstrftimestd::format (with chrono types)
Time zonesmanual / OS APIsstd::chrono::time_zone (with tzdata)

7. Hands-on timing examples

Example 1: measure a callable

#include <chrono>
#include <functional>
#include <iostream>
#include <thread>
template <typename Func, typename... Args>
auto measure_ms(Func&& f, Args&&... args) {
    auto start = std::chrono::steady_clock::now();
    std::invoke(std::forward<Func>(f), std::forward<Args>(args)...);
    auto end = std::chrono::steady_clock::now();
    return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
}
int main() {
    auto ms = measure_ms([] { std::this_thread::sleep_for(std::chrono::milliseconds(50)); });
    std::cout << "Elapsed: " << ms << " ms\n";
    return 0;
}

Example 2: RAII scope timer

#include <chrono>
#include <iostream>
#include <string>
#include <thread>
class ScopedTimer {
public:
    explicit ScopedTimer(const std::string& name)
        : name_(name), start_(std::chrono::steady_clock::now()) {}
    ~ScopedTimer() {
        auto end = std::chrono::steady_clock::now();
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start_).count();
        std::cout << "[" << name_ << "] " << ms << " ms\n";
    }
private:
    std::string name_;
    std::chrono::steady_clock::time_point start_;
};
void slowFunction() {
    ScopedTimer timer("slowFunction");
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int main() {
    slowFunction();
    return 0;
}

Example 3: timeout loop

#include <chrono>
#include <iostream>
#include <thread>
bool doWorkWithTimeout(std::chrono::milliseconds timeout) {
    auto deadline = std::chrono::steady_clock::now() + timeout;
    while (std::chrono::steady_clock::now() < deadline) {
        if (tryDoWork()) {
            return true;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    return false;
}
bool tryDoWork() {
    static int count = 0;
    return ++count >= 5;
}
int main() {
    if (doWorkWithTimeout(std::chrono::seconds(1))) {
        std::cout << "Success\n";
    } else {
        std::cout << "Timeout\n";
    }
    return 0;
}

Example 4: log timestamp (system_clock)

#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
std::string getTimestamp() {
    auto now = std::chrono::system_clock::now();
    auto tt = std::chrono::system_clock::to_time_t(now);
    std::tm tm_buf;
#ifdef _WIN32
    localtime_s(&tm_buf, &tt);
#else
    localtime_r(&tt, &tm_buf);
#endif
    std::ostringstream oss;
    oss << std::put_time(&tm_buf, "%Y-%m-%d %H:%M:%S");
    return oss.str();
}
int main() {
    std::cout << "[" << getTimestamp() << "] Application started\n";
    return 0;
}

Example 5: mixed duration arithmetic

#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;
    auto total = hours(1) + minutes(30) + seconds(45) + milliseconds(123);
    std::cout << "Total: " << duration_cast<milliseconds>(total).count() << " ms\n";
    auto fps = 60.0;
    auto frame_time = duration<double, std::ratio<1>>(1.0 / fps);
    auto frame_ms = duration_cast<milliseconds>(frame_time);
    std::cout << "60 FPS ≈ " << frame_ms.count() << " ms per frame\n";
    return 0;
}

Example 6: time() vs chrono resolution

ApproachTypical resolutionNTP-sensitiveCounts sleep (elapsed)Multithreading
time()1 sYesPoor for short waitsCoarse
clock()~ms (implementation)NoCPU time, not wall sleepProcess-wide CPU time
steady_clockns–µs classNoYesPer-call wall elapsed
system_clockns–µs classYesYesYes
#include <chrono>
#include <ctime>
#include <iostream>
#include <thread>
void compareResolution() {
    auto t1 = std::time(nullptr);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    auto t2 = std::time(nullptr);
    std::cout << "time(): " << (t2 - t1) << " s (actual ~50 ms)\n";
    auto start = std::chrono::steady_clock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    auto end = std::chrono::steady_clock::now();
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    std::cout << "chrono: " << ms << " ms\n";
}

Sample output:

time(): 0 s (actual ~50 ms)
chrono: 50 ms

8. Common errors and fixes

Error 1: using system_clock for timeouts

Symptom: After NTP adjustments, deadlines behave oddly.

// ❌ Risky for pure elapsed-time timeouts
auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(30);
while (condition && std::chrono::system_clock::now() < deadline) { /*...*/ }

Fix: Use steady_clock for elapsed time and timeouts.

// ✅ Elapsed-time timeout
auto start = std::chrono::steady_clock::now();
auto timeout = std::chrono::seconds(30);
while (condition && (std::chrono::steady_clock::now() - start < timeout)) { /*...*/ }

Error 2: ignoring truncation in duration_cast

Symptom: 1500ms cast to seconds becomes 1s.

auto ms = std::chrono::milliseconds(1500);
auto s = std::chrono::duration_cast<std::chrono::seconds>(ms);
// s.count() == 1

Fix: Use duration<double> or round/floor/ceil when you need a specific rounding rule.

auto ms = std::chrono::milliseconds(1500);
std::chrono::duration<double> sec(ms);
auto s = std::chrono::round<std::chrono::seconds>(ms);

Error 3: steady_clock for log timestamps

Symptom: Logs show meaningless huge tick counts.

Fix: Use system_clock (or a proper logging library) for human-readable timestamps.

Error 4: count() without remembering the unit

Symptom: d.count() depends on d’s type.

auto d = std::chrono::milliseconds(1500);
std::cout << d.count();  // 1500 — milliseconds
auto d2 = std::chrono::seconds(1);
std::cout << d2.count(); // 1 — seconds

Fix: Cast to the unit you mean before printing, or print the unit in the string.

Error 5: mixing different clocks’ time_points

Symptom: You cannot subtract system_clock::time_point from steady_clock::time_point.

// ❌ Does not compile
auto tp_sys = std::chrono::system_clock::now();
auto tp_steady = std::chrono::steady_clock::now();
// auto diff = tp_sys - tp_steady;

Fix: Perform arithmetic within one clock. C++20 adds clock_cast for controlled conversions when available.


9. Best practices

1. Pick a clock by job

JobPreferred clock
Benchmarkssteady_clock
Timeouts / elapsedsteady_clock
Log timestamps / calendarsystem_clock
Finest tick (after checking docs)high_resolution_clock

2. Readability with aliases and literals

using namespace std::chrono;
using namespace std::chrono_literals;
auto timeout = 30s;
auto delay = 100ms;
auto deadline = steady_clock::now() + timeout;

chrono_literals (C++14)

#include <chrono>
using namespace std::chrono_literals;
auto d1 = 1s;
auto d2 = 100ms;
auto d3 = 1.5min;

4. Pass duration in APIs

void setTimeout(std::chrono::milliseconds ms);
std::chrono::milliseconds getElapsed();
// Avoid: void setTimeout(int x); // seconds? milliseconds?

5. Warm up benchmarks

for (int i = 0; i < 3; ++i) {
    doWork();
}
auto start = std::chrono::steady_clock::now();
for (int i = 0; i < 100; ++i) {
    doWork();
}
auto end = std::chrono::steady_clock::now();
auto avg = (end - start) / 100;

10. Production patterns

Pattern 1: reusable timer class

#include <chrono>
#include <functional>
#include <iostream>
#include <thread>
class Timer {
public:
    using Callback = std::function<void(std::chrono::milliseconds)>;
    void start() {
        start_ = std::chrono::steady_clock::now();
    }
    std::chrono::milliseconds elapsed() const {
        auto now = std::chrono::steady_clock::now();
        return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_);
    }
    void stopAndReport(Callback cb) {
        cb(elapsed());
    }
private:
    std::chrono::steady_clock::time_point start_;
};
int main() {
    Timer t;
    t.start();
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    t.stopAndReport([](std::chrono::milliseconds ms) {
        std::cout << "Elapsed: " << ms.count() << " ms\n";
    });
    return 0;
}

Pattern 2: cache TTL

#include <chrono>
#include <optional>
#include <unordered_map>
template <typename K, typename V>
class TimedCache {
public:
    using Clock = std::chrono::steady_clock;
    using TimePoint = Clock::time_point;
    using Duration = std::chrono::seconds;
    explicit TimedCache(Duration ttl) : ttl_(ttl) {}
    void insert(const K& key, const V& value) {
        cache_[key] = {value, Clock::now()};
    }
    std::optional<V> get(const K& key) {
        auto it = cache_.find(key);
        if (it == cache_.end()) return std::nullopt;
        if (Clock::now() - it->second.second > ttl_) {
            cache_.erase(it);
            return std::nullopt;
        }
        return it->second.first;
    }
private:
    Duration ttl_;
    std::unordered_map<K, std::pair<V, TimePoint>> cache_;
};
int main() {
    TimedCache<std::string, int> cache(std::chrono::seconds(60));
    cache.insert("key", 42);
    if (auto v = cache.get("key")) {
        std::cout << "Value: " << *v << "\n";
    }
    return 0;
}

Pattern 3: Boost.Asio steady timer

#include <boost/asio.hpp>
#include <chrono>
#include <iostream>
void runWithTimeout(boost::asio::io_context& io, std::chrono::seconds timeout) {
    boost::asio::steady_timer timer(io, timeout);
    timer.async_wait([](const boost::system::error_code& ec) {
        if (!ec) {
            std::cout << "Timeout!\n";
        }
    });
    io.run();
}

Pattern 4: fixed frame rate

#include <chrono>
#include <functional>
#include <thread>
void runAtFixedRate(std::chrono::milliseconds frameTime,
                    std::function<void()> update,
                    std::function<bool()> isRunning) {
    auto nextFrame = std::chrono::steady_clock::now();
    while (isRunning()) {
        update();
        nextFrame += frameTime;
        std::this_thread::sleep_until(nextFrame);
    }
}

Pattern 5: subsecond in logs (C++20 sketch)

#if __cplusplus >= 202002L
#include <chrono>
#include <format>
#include <iostream>
void logWithMicroseconds() {
    auto now = std::chrono::system_clock::now();
    auto us = std::chrono::duration_cast<std::chrono::microseconds>(
        now.time_since_epoch()) % 1000000;
    auto tt = std::chrono::system_clock::to_time_t(now);
    std::tm* tm = std::localtime(&tt);
    std::cout << std::format("{:%Y-%m-%d %H:%M:%S}.{:06d}\n",
                             *tm, static_cast<int>(us.count()));
}
#endif

11. Checklist

  • Use steady_clock for benchmarks and timeouts
  • Use system_clock for wall-clock timestamps
  • Remember truncation when using duration_cast
  • Prefer chrono_literals for readability
  • Expose std::chrono::duration in function signatures
  • Do not mix time_points from different clocks blindly
  • When printing count(), state the unit

12. Summary

ConceptSummary
durationA length of time: seconds, milliseconds, …
time_pointAn instant on a given clock’s timeline
system_clockWall time; may step; to_time_t
steady_clockMonotonic; best for benchmarks and timeouts
duration_castUnit conversion; mind truncation; floor/ceil/round in C++17

Rules of thumb:

  • Measure elapsed / timeoutssteady_clock
  • Show calendar timesystem_clock
  • Convert unitsduration_cast (watch truncation)

Frequently asked questions (FAQ)

Q. Where does this matter in production?

A. Anywhere you need stable elapsed time, deadlines, TTLs, or readable timestamps. Prefer typed durations over raw integers.

A. Follow the links at the bottom of each post, or use the C++ series index.

Q. How do I go deeper?

A. Read cppreference and experiment with C++20 calendar and timezone on a recent toolchain.

References


  • C++ profiling — perf, gprof
  • C++ logging with spdlog
  • Boost.Asio introduction

Practical checklist

Before coding

  • Is this the right tool for the problem?
  • Will teammates understand and maintain it?
  • Does it meet performance requirements?

While coding

  • Warnings addressed?
  • Edge cases considered?
  • Errors handled appropriately?

At review

  • Intent is clear?
  • Tests sufficient?
  • Documentation updated?

Keywords

C++, std::chrono, duration, time_point, steady_clock, system_clock, duration_cast, C++11, timing, benchmark


More on this site


자주 묻는 질문 (FAQ)

Q. 이 내용을 실무에서 언제 쓰나요?

A. Replace time() with std::chrono: duration, time_point, system_clock, steady_clock, duration_cast, benchmarks, timeouts, … 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.

Q. 선행으로 읽으면 좋은 글은?

A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.

Q. 더 깊이 공부하려면?

A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.


같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

C++, std::chrono, duration, time_point, steady_clock, system_clock, duration_cast 등으로 검색하시면 이 글이 도움이 됩니다.