경고: 이 문서의 오래된 판을 편집하고 있습니다. 이것을 게시하면, 이 판 이후로 바뀐 모든 편집이 사라집니다.귀하는 로그인되어 있지 않습니다. 이대로 편집하면 귀하의 IP 주소가 편집 기록에 남게 됩니다.스팸 방지 검사입니다. 이것을 입력하지 마세요!==개요== '''std::chrono'''는 C++11부터 표준 라이브러리에 추가된 시간 관련 기능을 제공하는 라이브러리이다. 이 라이브러리는 고정밀의 시간 측정, 시간 간격 계산, 그리고 다양한 시간 단위 간의 변환을 지원한다. 기존의 C 스타일 시간 함수들과 달리 타입 안전성을 보장하며, 컴파일 타임에 단위 변환 오류를 감지할 수 있다. chrono 라이브러리는 다음과 같은 주요 구성 요소로 이루어져 있다: * '''Clock''': 시간을 측정하는 시계 * '''Time Point''': 특정 시점을 나타내는 객체 * '''Duration''': 시간 간격을 나타내는 객체 ==주요 구성 요소== ===Clock 타입=== chrono 라이브러리는 다음과 같은 세 가지 주요 clock을 제공한다: ====system_clock==== 시스템의 실시간 시계를 나타낸다. 이 시계는 시스템 관리자가 조정할 수 있으며, UTC 시간을 기준으로 한다. 일반적으로 [[유닉스 시간|Unix epoch]](1970년 1월 1일 00:00:00 UTC)부터의 시간을 측정한다. <syntaxhighlight lang="c++"> auto now = std::chrono::system_clock::now(); std::time_t time_t_now = std::chrono::system_clock::to_time_t(now); </syntaxhighlight> ====steady_clock==== 단조 증가하는 시계로, 시스템 시간 조정의 영향을 받지 않는다. 성능 측정에 가장 적합한 시계이다. 이 시계는 절대 뒤로 가지 않으며, 균등한 속도로 진행된다. <syntaxhighlight lang="c++"> auto start = std::chrono::steady_clock::now(); // 측정할 코드 auto end = std::chrono::steady_clock::now(); </syntaxhighlight> ====high_resolution_clock==== 사용 가능한 가장 높은 해상도의 시계이다. 일반적으로 steady_clock의 별칭이다. ===Duration=== 시간 간격을 나타내는 템플릿 클래스이다. 두 개의 템플릿 매개변수를 가진다: * '''Rep''': 틱의 개수를 저장하는 산술 타입 * '''Period''': 각 틱이 나타내는 시간 간격 (std::ratio로 표현) 표준 라이브러리는 다음과 같은 미리 정의된 duration 타입들을 제공한다: * '''nanoseconds''': 나노초 (10^-9 초) * '''microseconds''': 마이크로초 (10^-6 초) * '''milliseconds''': 밀리초 (10^-3 초) * '''seconds''': 초 * '''minutes''': 분 * '''hours''': 시간 ===Time Point=== 특정 시점을 나타내는 템플릿 클래스이다. 특정 epoch(기준점)으로부터의 duration으로 표현된다. ==틱과 정밀도== '''틱'''<ref>한 틱이 1초이면 1초 간격으로 측정한다는 것이다. 틱의 간격이 클수록 부정확해진다. 예를 들어 한 틱이 1초이면 1.4초에 실행된 코드는 1초로 취급된다.</ref>은 시간 측정의 최소 단위이다. chrono 라이브러리에서는 나노초(ns), 마이크로초(μs), 밀리초(ms), 초(s), 분(m), 시간(h) 등 다양한 단위를 선택할 수 있다. 시간 측정의 정밀도는 사용하는 시계와 시스템에 따라 달라진다. 일반적으로 steady_clock이 가장 정확한 성능 측정을 제공한다. ==기본 사용법== ===간단한 시간 측정=== <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> #include <thread> int main() { using namespace std::chrono; // 시작 시간 기록 auto start = steady_clock::now(); // 측정할 코드 (예: 1초 대기) std::this_thread::sleep_for(milliseconds(1000)); // 종료 시간 기록 auto end = steady_clock::now(); // 경과 시간 계산 auto duration = end - start; // 다양한 단위로 출력 auto ns = duration_cast<nanoseconds>(duration); auto ms = duration_cast<milliseconds>(duration); auto sec = duration_cast<seconds>(duration); std::cout << "경과 시간: " << ns.count() << "ns, " << ms.count() << "ms, " << sec.count() << "초" << std::endl; return 0; } </syntaxhighlight> ===함수 실행 시간 측정=== <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> #include <vector> #include <algorithm> // 측정할 함수 void heavy_computation() { std::vector<int> vec(1000000); std::iota(vec.begin(), vec.end(), 1); std::sort(vec.begin(), vec.end(), std::greater<int>()); } int main() { using namespace std::chrono; auto start = high_resolution_clock::now(); heavy_computation(); auto end = high_resolution_clock::now(); auto duration = duration_cast<microseconds>(end - start); std::cout << "함수 실행 시간: " << duration.count() << " 마이크로초" << std::endl; return 0; } </syntaxhighlight> ===시간 측정 클래스=== 재사용 가능한 시간 측정 클래스를 만들 수 있다: <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> class Timer { private: std::chrono::steady_clock::time_point start_time; public: Timer() : start_time(std::chrono::steady_clock::now()) {} void reset() { start_time = std::chrono::steady_clock::now(); } double elapsed_seconds() const { auto end_time = std::chrono::steady_clock::now(); auto duration = end_time - start_time; return std::chrono::duration<double>(duration).count(); } long long elapsed_milliseconds() const { auto end_time = std::chrono::steady_clock::now(); return std::chrono::duration_cast<std::chrono::milliseconds>( end_time - start_time).count(); } }; int main() { Timer timer; // 어떤 작업 수행 std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::cout << "경과 시간: " << timer.elapsed_seconds() << "초" << std::endl; std::cout << "경과 시간: " << timer.elapsed_milliseconds() << "ms" << std::endl; return 0; } </syntaxhighlight> ==고급 사용법== ===Duration 산술 연산=== <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> int main() { using namespace std::chrono; auto d1 = milliseconds(100); auto d2 = seconds(2); // Duration 더하기 auto total = d1 + d2; std::cout << "총 시간: " << duration_cast<milliseconds>(total).count() << "ms" << std::endl; // Duration 비교 if (d1 < d2) { std::cout << "d1이 d2보다 짧습니다." << std::endl; } // Duration 곱하기/나누기 auto doubled = d1 * 2; auto half = d2 / 2; std::cout << "두 배: " << doubled.count() << "ms" << std::endl; std::cout << "절반: " << duration_cast<milliseconds>(half).count() << "ms" << std::endl; return 0; } </syntaxhighlight> ===벤치마킹 함수=== <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> #include <functional> template<typename Func> double benchmark(Func&& func, int iterations = 1) { using namespace std::chrono; auto start = steady_clock::now(); for (int i = 0; i < iterations; ++i) { func(); } auto end = steady_clock::now(); auto duration = duration_cast<nanoseconds>(end - start); return static_cast<double>(duration.count()) / iterations; } int main() { auto result = benchmark([]() { volatile int sum = 0; for (int i = 0; i < 1000; ++i) { sum += i; } }, 10000); std::cout << "평균 실행 시간: " << result << " 나노초" << std::endl; return 0; } </syntaxhighlight> ==성능 측정 시 주의사항== ===컴파일러 최적화=== 성능 측정 시 컴파일러의 최적화로 인해 측정하려는 코드가 제거될 수 있다. 이를 방지하기 위해 다음과 같은 방법을 사용할 수 있다: <syntaxhighlight lang="c++"> // volatile 키워드 사용 volatile int result = expensive_calculation(); // 컴파일러 barrier 사용 (GCC/Clang) asm volatile("" ::: "memory"); // std::atomic 사용 std::atomic<int> atomic_result{0}; atomic_result.store(expensive_calculation()); </syntaxhighlight> ===시계 선택=== * '''성능 측정''': steady_clock 사용 권장 * '''실제 시간''': system_clock 사용 * '''가장 높은 정밀도''': high_resolution_clock 사용 ===측정 정확도=== 매우 짧은 시간을 측정할 때는 측정 오버헤드를 고려해야 한다. 여러 번 실행하여 평균을 구하는 것이 좋다. ==실용적인 예제== ===프로파일링 매크로=== <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> #define PROFILE_SCOPE(name) ProfileTimer timer(name) #define PROFILE_FUNCTION() PROFILE_SCOPE(__FUNCTION__) class ProfileTimer { private: const char* name; std::chrono::steady_clock::time_point start; public: ProfileTimer(const char* name) : name(name), start(std::chrono::steady_clock::now()) {} ~ProfileTimer() { auto end = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); std::cout << "[PROFILE] " << name << ": " << duration.count() << "μs" << std::endl; } }; void slow_function() { PROFILE_FUNCTION(); // 시뮬레이션된 작업 std::this_thread::sleep_for(std::chrono::milliseconds(100)); } int main() { { PROFILE_SCOPE("Main Block"); slow_function(); { PROFILE_SCOPE("Inner Block"); std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } return 0; } </syntaxhighlight> ===타임아웃 구현=== <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> #include <thread> class Timeout { private: std::chrono::steady_clock::time_point start; std::chrono::steady_clock::duration limit; public: template<typename Rep, typename Period> Timeout(const std::chrono::duration<Rep, Period>& timeout_duration) : start(std::chrono::steady_clock::now()), limit(timeout_duration) {} bool expired() const { return (std::chrono::steady_clock::now() - start) >= limit; } std::chrono::milliseconds remaining() const { auto elapsed = std::chrono::steady_clock::now() - start; auto remaining_duration = limit - elapsed; return std::chrono::duration_cast<std::chrono::milliseconds>(remaining_duration); } }; int main() { Timeout timeout(std::chrono::seconds(5)); while (!timeout.expired()) { std::cout << "남은 시간: " << timeout.remaining().count() << "ms" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(500)); } std::cout << "타임아웃!" << std::endl; return 0; } </syntaxhighlight> ==시간 변환과 형식화== ===시간 단위 변환=== <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> int main() { using namespace std::chrono; // 다양한 단위로 시간 생성 auto ns = nanoseconds(1234567890); // 상위 단위로 변환 auto ms = duration_cast<milliseconds>(ns); auto sec = duration_cast<seconds>(ns); std::cout << ns.count() << " 나노초는" << std::endl; std::cout << ms.count() << " 밀리초 또는" << std::endl; std::cout << sec.count() << " 초입니다." << std::endl; // 부동소수점 변환 duration<double, std::milli> precise_ms = ns; std::cout << "정확한 밀리초: " << precise_ms.count() << "ms" << std::endl; return 0; } </syntaxhighlight> ===시간 형식화=== <syntaxhighlight lang="c++" line=""> #include <iostream> #include <chrono> #include <iomanip> #include <sstream> std::string format_duration(std::chrono::nanoseconds ns) { using namespace std::chrono; auto hours = duration_cast<std::chrono::hours>(ns); ns -= hours; auto minutes = duration_cast<std::chrono::minutes>(ns); ns -= minutes; auto seconds = duration_cast<std::chrono::seconds>(ns); ns -= seconds; auto milliseconds = duration_cast<std::chrono::milliseconds>(ns); std::stringstream ss; ss << std::setfill('0') << std::setw(2) << hours.count() << ":" << std::setw(2) << minutes.count() << ":" << std::setw(2) << seconds.count() << "." << std::setw(3) << milliseconds.count(); return ss.str(); } int main() { auto duration = std::chrono::nanoseconds(3723456789000); // 1시간 2분 3초 456ms std::cout << "형식화된 시간: " << format_duration(duration) << std::endl; return 0; } </syntaxhighlight> ==플랫폼별 고려사항== ===Windows=== Windows에서는 QueryPerformanceCounter를 기반으로 하는 고해상도 타이머를 사용한다. 일반적으로 마이크로초 단위의 정밀도를 제공한다. ===Linux/Unix=== Linux에서는 clock_gettime 시스템 콜을 사용하며, CLOCK_MONOTONIC을 통해 단조 증가하는 시간을 제공한다. ===성능 특성=== * '''system_clock''': 중간 정도의 오버헤드, 시스템 시간 조정 영향 받음 * '''steady_clock''': 낮은 오버헤드, 단조 증가 보장 * '''high_resolution_clock''': 플랫폼에 따라 다름 ==활용 분야== * '''성능 분석''': 함수나 알고리즘의 실행 시간 측정 * '''프로파일링''': 코드의 병목 지점 찾기 * '''타임아웃 구현''': 일정 시간 후 작업 중단 * '''애니메이션''': 프레임 타이밍 제어 * '''벤치마킹''': 다양한 구현의 성능 비교 * '''실시간 시스템''': 정확한 타이밍 제어 ==참고 자료== * [https://en.cppreference.com/w/cpp/chrono C++ Reference - Chrono] * [https://www.cplusplus.com/reference/chrono/ CPlusPlus.com - Chrono] * ISO/IEC 14882:2011 (C++11 표준) ==각주== <references /> ==같이 보기== * [[C++ 표준 라이브러리]] * [[시간 복잡도]] * [[성능 분석]] * [[C++ 11]] [[분류:C++]] [[분류:C++ 라이브러리]] [[분류:시간 라이브러리]] [[분류:성능 측정]] [[분류:프로그래밍 도구]] 편집 요약 가온 위키에서의 모든 기여는 크리에이티브 커먼즈 저작자표시-동일조건변경허락 라이선스로 배포된다는 점을 유의해 주세요(자세한 내용에 대해서는 가온 위키:저작권 문서를 읽어주세요). 만약 여기에 동의하지 않는다면 문서를 저장하지 말아 주세요. 또한, 직접 작성했거나 퍼블릭 도메인과 같은 자유 문서에서 가져왔다는 것을 보증해야 합니다. 저작권이 있는 내용을 허가 없이 저장하지 마세요! 취소 편집 도움말 (새 창에서 열림)