콘텐츠로 이동

<chrono> 시간 측정 & 타이머

C++ <chrono>는 타입 안전한 시간 계산을 위한 라이브러리입니다. 정수나 double로 시간을 다루던 구식 방식 대신, 단위 변환 실수를 컴파일 타임에 잡아줍니다.


Clock ──produces──▶ time_point ──difference──▶ duration
개념설명예시
Clock현재 시각을 제공하는 시계steady_clock, system_clock
time_point특정 시각 (Epoch 기준)steady_clock::now()
duration두 시각의 차이milliseconds(100)

#include <chrono>
using namespace std::chrono;
// 단조증가 시계 — 성능 측정에 사용 (시스템 시간 변경 영향 없음)
auto t1 = steady_clock::now();
// 시스템 시계 — 실제 시각 표현 (UTC 기준)
auto now = system_clock::now();
// 고해상도 시계 — 플랫폼에 따라 steady_clock과 동일할 수 있음
auto t = high_resolution_clock::now();

성능 측정에는 반드시 steady_clock을 사용하세요. system_clock은 NTP 동기화나 사용자 조작으로 역행할 수 있습니다.


#include <chrono>
using namespace std::chrono;
duration<long long, std::nano> ns(1000); // 1000 나노초
duration<long long, std::micro> us(500); // 500 마이크로초
duration<long long, std::milli> ms(250); // 250 밀리초
duration<long long> sec(10); // 10 초
duration<long long, std::ratio<60>> min(5); // 5 분
// 편의 타입 별칭
nanoseconds n(1000);
microseconds u(500);
milliseconds m(250);
seconds s(10);
minutes m2(5);
hours h(2);
auto ms = milliseconds(1500);
// 정밀도 손실 없는 변환 (작은 → 큰 단위는 암시적)
seconds sec = duration_cast<seconds>(ms); // 1 (소수 버림)
// 명시적 변환 필요 (큰 → 작은 단위는 암시적 OK)
auto us = microseconds(ms); // 1500000
// 부동소수점 duration
duration<double> fsec = ms; // 1.5

using namespace std::chrono_literals;
auto delay = 100ms; // milliseconds(100)
auto period = 1s; // seconds(1)
auto wait = 500us; // microseconds(500)
auto big = 2h + 30min + 15s; // 복합 연산
// std::this_thread::sleep_for와 함께
#include <thread>
std::this_thread::sleep_for(50ms);

#include <chrono>
#include <iostream>
template <typename Func>
auto benchmark(Func&& f) {
using namespace std::chrono;
auto start = steady_clock::now();
f();
auto end = steady_clock::now();
return duration_cast<microseconds>(end - start);
}
int main() {
auto elapsed = benchmark([]() {
volatile int sum = 0;
for (int i = 0; i < 1'000'000; ++i) sum += i;
});
std::cout << "Elapsed: " << elapsed.count() << " us\n";
}
#include <chrono>
#include <iostream>
#include <string>
class ScopedTimer {
public:
explicit ScopedTimer(std::string label)
: label_(std::move(label))
, start_(std::chrono::steady_clock::now()) {}
~ScopedTimer() {
auto end = std::chrono::steady_clock::now();
auto us = std::chrono::duration_cast<std::chrono::microseconds>(
end - start_).count();
std::cout << label_ << ": " << us << " us\n";
}
private:
std::string label_;
std::chrono::steady_clock::time_point start_;
};
// 사용
void expensiveOp() {
ScopedTimer t("expensiveOp");
// ... 코드 ...
}
template <int N = 10, typename Func>
double benchmark_avg(Func&& f) {
using namespace std::chrono;
double total = 0;
for (int i = 0; i < N; ++i) {
auto start = steady_clock::now();
f();
auto end = steady_clock::now();
total += duration<double, std::micro>(end - start).count();
}
return total / N;
}

#include <chrono>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void waitWithTimeout() {
using namespace std::chrono_literals;
std::unique_lock lock(mtx);
// 최대 500ms 대기
if (cv.wait_for(lock, 500ms, []{ return ready; })) {
std::cout << "조건 충족\n";
} else {
std::cout << "타임아웃\n";
}
}

C++20에서 날짜/시간 계산 API가 크게 확장되었습니다.

#include <chrono>
using namespace std::chrono;
// 날짜 리터럴 (C++20)
auto d = 2024y / January / 15; // year_month_day
auto d2 = 2024y / 1 / 15;
// 오늘 날짜
auto today = floor<days>(system_clock::now());
year_month_day ymd{today};
std::cout << ymd.year() << "-"
<< static_cast<unsigned>(ymd.month()) << "-"
<< static_cast<unsigned>(ymd.day()) << "\n";
// 날짜 연산
auto next_month = ymd.year() / (ymd.month() + months(1)) / ymd.day();
// 타임존 (C++20)
auto tz = locate_zone("Asia/Seoul");
auto now = zoned_time{tz, system_clock::now()};
std::cout << now << "\n"; // 2024-01-15 14:30:00 KST
auto deadline = sys_days{2024y / December / 31};
auto now_days = floor<days>(system_clock::now());
auto remaining = deadline - now_days;
std::cout << remaining.count() << "일 남음\n";

#include <chrono>
class GameTimer {
public:
using Clock = std::chrono::steady_clock;
GameTimer() : last_(Clock::now()) {}
// 매 프레임 호출 — deltaTime(초) 반환
float tick() {
auto now = Clock::now();
float dt = std::chrono::duration<float>(now - last_).count();
last_ = now;
return dt;
}
// 경과 시간 (초)
float elapsed() const {
return std::chrono::duration<float>(Clock::now() - start_).count();
}
private:
Clock::time_point start_ = Clock::now();
Clock::time_point last_;
};
// 사용
GameTimer timer;
while (running) {
float dt = timer.tick();
update(dt); // dt: 프레임 간 경과 시간
render();
}

// 잘못된 예 — system_clock으로 성능 측정
auto t1 = std::chrono::system_clock::now();
doWork();
auto t2 = std::chrono::system_clock::now();
// NTP 조정 시 음수가 나올 수 있음!
// 올바른 예
auto t1 = std::chrono::steady_clock::now();
doWork();
auto t2 = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);

  • 성능 측정 → steady_clock
  • 실제 시각 표현 → system_clock
  • 단위 변환 → duration_cast<> 또는 부동소수점 duration<double>
  • 리터럴 → using namespace std::chrono_literals + 100ms, 1s
  • C++20 날짜 → year_month_day, zoned_time