Chrono: 두 판 사이의 차이

Gaon12 (토론 / 기여)
계산 원리 추가
Gaon12 (토론 / 기여)
Duration: 수식 적용
 
(같은 사용자의 중간 판 하나는 보이지 않습니다)
1번째 줄: 1번째 줄:
==개요==
==개요==
C++ 11부터 추가된 시간 라이브러리. 고정밀의 시간 측정이 가능하다.
'''std::chrono'''는 C++11부터 표준 라이브러리에 추가된 시간 관련 기능을 제공하는 라이브러리이다. 이 라이브러리는 고정밀의 시간 측정, 시간 간격 계산, 그리고 다양한 시간 단위 간의 변환을 지원한다. 기존의 C 스타일 시간 함수들과 달리 타입 안전성을 보장하며, 컴파일 타임에 단위 변환 오류를 감지할 수 있다.
==틱==
틱<ref>한 틱이 1초이면 1초 간격으로 측정한다는 것이다. 틱의 간격이 클수록 부정확해진다. 예를 들어 한 틱이 1초이면 1.4초에 실행된 코드는 1초로 취급된다.</ref> 범위를 선택할 수 있다. 나노초(ns), 밀리초(ms), 초(s), 분(m), 시간(h) 단위를 선택할 수 있다.


계산 원리는 코드 작동 종료 시점의 시간에서 시작 시점의 시간을 빼 소요 시간을 계산하는 것이다.
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''': 각 틱이 나타내는 시간 간격 (<code><nowiki>std::ratio</nowiki></code>로 표현)
 
표준 라이브러리는 다음과 같은 미리 정의된 duration 타입들을 제공한다:
* '''nanoseconds''': 나노초 (<math>10^{-9}</math> 초)
* '''microseconds''': 마이크로초 (<math>10^{-6}</math> 초) 
* '''milliseconds''': 밀리초 (<math>10^{-3}</math> 초)
* '''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="">
<syntaxhighlight lang="c++" line="">
#include <iostream>
#include <iostream>
#include <chrono>
#include <chrono>
using namespace std;
#include <thread>
using namespace chrono;


int maint(){
int main() {
  system_clock::time_point StartTime = system_clock::now();//시작 시간 계산 시작
    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>


  cout << "Hello world!";
===함수 실행 시간 측정===
<syntaxhighlight lang="c++" line="">
#include <iostream>
#include <chrono>
#include <vector>
#include <algorithm>


  system_clock::time_point EndTime = system_clock::now();//종료 시간 계산 시작
// 측정할 함수
  duration<double> DefaultSec = EndTime - StartTime;
void heavy_computation() {
  nanoseconds nano = duration_cast<nanoseconds>(EndTime - StartTime); //나노초 계산
    std::vector<int> vec(1000000);
  milliseconds mill = duration_cast<milliseconds>(EndTime - StartTime); //밀리초 계산
    std::iota(vec.begin(), vec.end(), 1);
  seconds sec = duration_cast<seconds>(EndTime - StartTime); //초 계산
    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>


  cout << nano << "ns " << mill << "ms " << sec << "초";
===시간 측정 클래스===
재사용 가능한 시간 측정 클래스를 만들 수 있다:


<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>
</syntaxhighlight>
9번째 줄 코드를 실행하기 전에 7번째 줄에서 시작 시간을 표시하고, 11번째 줄에서 종료 시간을 표시한 뒤, '''종료 시간 - 시작 시간'''을 하여 나온 값을 각각 나노초, 밀리초, 초로 변환하여 17번째 줄에서 출력하는 코드이다.
 
==고급 사용법==
 
===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 />
<references />


[[분류:C++]]  
==같이 보기==
[[분류:C++ 라이브러리]]  
* [[C++ 표준 라이브러리]]
* [[시간 복잡도]]
* [[성능 분석]]
* [[C++ 11]]
 
[[분류:C++]]
[[분류:C++ 라이브러리]]
[[분류:시간 라이브러리]]
[[분류:시간 라이브러리]]
[[분류:성능 측정]]
[[분류:프로그래밍 도구]]

2025년 8월 7일 (목) 12:13 기준 최신판

개요[편집 / 원본 편집]

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)부터의 시간을 측정한다.

auto now = std::chrono::system_clock::now();
std::time_t time_t_now = std::chrono::system_clock::to_time_t(now);

steady_clock[편집 / 원본 편집]

단조 증가하는 시계로, 시스템 시간 조정의 영향을 받지 않는다. 성능 측정에 가장 적합한 시계이다. 이 시계는 절대 뒤로 가지 않으며, 균등한 속도로 진행된다.

auto start = std::chrono::steady_clock::now();
// 측정할 코드
auto end = std::chrono::steady_clock::now();

high_resolution_clock[편집 / 원본 편집]

사용 가능한 가장 높은 해상도의 시계이다. 일반적으로 steady_clock의 별칭이다.

Duration[편집 / 원본 편집]

시간 간격을 나타내는 템플릿 클래스이다. 두 개의 템플릿 매개변수를 가진다:

  • Rep: 틱의 개수를 저장하는 산술 타입
  • Period: 각 틱이 나타내는 시간 간격 (std::ratio로 표현)

표준 라이브러리는 다음과 같은 미리 정의된 duration 타입들을 제공한다:

  • nanoseconds: 나노초 ([math]\displaystyle{ 10^{-9} }[/math] 초)
  • microseconds: 마이크로초 ([math]\displaystyle{ 10^{-6} }[/math] 초)
  • milliseconds: 밀리초 ([math]\displaystyle{ 10^{-3} }[/math] 초)
  • seconds: 초
  • minutes: 분
  • hours: 시간

Time Point[편집 / 원본 편집]

특정 시점을 나타내는 템플릿 클래스이다. 특정 epoch(기준점)으로부터의 duration으로 표현된다.

틱과 정밀도[편집 / 원본 편집]

[1]은 시간 측정의 최소 단위이다. chrono 라이브러리에서는 나노초(ns), 마이크로초(μs), 밀리초(ms), 초(s), 분(m), 시간(h) 등 다양한 단위를 선택할 수 있다.

시간 측정의 정밀도는 사용하는 시계와 시스템에 따라 달라진다. 일반적으로 steady_clock이 가장 정확한 성능 측정을 제공한다.

기본 사용법[편집 / 원본 편집]

간단한 시간 측정[편집 / 원본 편집]

#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;
}

함수 실행 시간 측정[편집 / 원본 편집]

#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;
}

시간 측정 클래스[편집 / 원본 편집]

재사용 가능한 시간 측정 클래스를 만들 수 있다:

#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;
}

고급 사용법[편집 / 원본 편집]

Duration 산술 연산[편집 / 원본 편집]

#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;
}

벤치마킹 함수[편집 / 원본 편집]

#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;
}

성능 측정 시 주의사항[편집 / 원본 편집]

컴파일러 최적화[편집 / 원본 편집]

성능 측정 시 컴파일러의 최적화로 인해 측정하려는 코드가 제거될 수 있다. 이를 방지하기 위해 다음과 같은 방법을 사용할 수 있다:

// 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());

시계 선택[편집 / 원본 편집]

  • 성능 측정: steady_clock 사용 권장
  • 실제 시간: system_clock 사용
  • 가장 높은 정밀도: high_resolution_clock 사용

측정 정확도[편집 / 원본 편집]

매우 짧은 시간을 측정할 때는 측정 오버헤드를 고려해야 한다. 여러 번 실행하여 평균을 구하는 것이 좋다.

실용적인 예제[편집 / 원본 편집]

프로파일링 매크로[편집 / 원본 편집]

#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;
}

타임아웃 구현[편집 / 원본 편집]

#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;
}

시간 변환과 형식화[편집 / 원본 편집]

시간 단위 변환[편집 / 원본 편집]

#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;
}

시간 형식화[편집 / 원본 편집]

#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;
}

플랫폼별 고려사항[편집 / 원본 편집]

Windows[편집 / 원본 편집]

Windows에서는 QueryPerformanceCounter를 기반으로 하는 고해상도 타이머를 사용한다. 일반적으로 마이크로초 단위의 정밀도를 제공한다.

Linux/Unix[편집 / 원본 편집]

Linux에서는 clock_gettime 시스템 콜을 사용하며, CLOCK_MONOTONIC을 통해 단조 증가하는 시간을 제공한다.

성능 특성[편집 / 원본 편집]

  • system_clock: 중간 정도의 오버헤드, 시스템 시간 조정 영향 받음
  • steady_clock: 낮은 오버헤드, 단조 증가 보장
  • high_resolution_clock: 플랫폼에 따라 다름

활용 분야[편집 / 원본 편집]

  • 성능 분석: 함수나 알고리즘의 실행 시간 측정
  • 프로파일링: 코드의 병목 지점 찾기
  • 타임아웃 구현: 일정 시간 후 작업 중단
  • 애니메이션: 프레임 타이밍 제어
  • 벤치마킹: 다양한 구현의 성능 비교
  • 실시간 시스템: 정확한 타이밍 제어

참고 자료[편집 / 원본 편집]

각주[편집 / 원본 편집]

  1. 한 틱이 1초이면 1초 간격으로 측정한다는 것이다. 틱의 간격이 클수록 부정확해진다. 예를 들어 한 틱이 1초이면 1.4초에 실행된 코드는 1초로 취급된다.

같이 보기[편집 / 원본 편집]

최근 바뀜

더 보기