C++学习笔记-计时

C++11引入的chrono库提供了精确的时间测量功能,可以用于性能分析、基准测试和程序优化。通过创建简单的计时器类,我们可以方便地测量代码执行时间。

基本计时器实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <chrono>
#include <thread>

void Function()
{
    for (int i = 0; i < 100; i++)
        std::cout << "Hello" << std::endl;
}

/* 写一个简单的计时器类 */
struct Timer
{
    std::chrono::time_point<std::chrono::steady_clock> start, end;

    Timer()
    {
        start = std::chrono::high_resolution_clock::now(); // 开始时获取当前时间
    }

    ~Timer()
    {
        end = std::chrono::high_resolution_clock::now(); // 析构函数在结束时获取当前时间
        auto duration = end - start;
        float ms = duration.count() * 1000.0f; // 获取毫秒值
        std::cout << "Timer: " << ms << "ms" << std::endl;
    }
};

int main()
{
    Timer timer;
    Function();
    
    return 0;
}

改进的计时器类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <iostream>
#include <chrono>
#include <string>

class PrecisionTimer
{
private:
    std::chrono::time_point<std::chrono::high_resolution_clock> m_StartTime;
    std::string m_Name;
    
public:
    PrecisionTimer(const std::string& name = "Timer") : m_Name(name)
    {
        m_StartTime = std::chrono::high_resolution_clock::now();
    }
    
    ~PrecisionTimer()
    {
        Stop();
    }
    
    void Stop()
    {
        auto endTime = std::chrono::high_resolution_clock::now();
        auto duration = endTime - m_StartTime;
        
        // 转换为不同的时间单位
        auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
        auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(duration).count();
        auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
        auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
        
        std::cout << m_Name << " took:" << std::endl;
        std::cout << "  " << nanoseconds << " nanoseconds" << std::endl;
        std::cout << "  " << microseconds << " microseconds" << std::endl;
        std::cout << "  " << milliseconds << " milliseconds" << std::endl;
        std::cout << "  " << seconds << " seconds" << std::endl;
    }
    
    // 获取经过的时间(不停止计时器)
    template<typename T = std::chrono::milliseconds>
    long long GetElapsed() const
    {
        auto currentTime = std::chrono::high_resolution_clock::now();
        auto duration = currentTime - m_StartTime;
        return std::chrono::duration_cast<T>(duration).count();
    }
    
    // 重置计时器
    void Reset()
    {
        m_StartTime = std::chrono::high_resolution_clock::now();
    }
};

void TestFunction1()
{
    // 模拟一些计算工作
    volatile int sum = 0;
    for (int i = 0; i < 1000000; ++i)
    {
        sum += i;
    }
}

void TestFunction2()
{
    // 模拟I/O操作
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

int main()
{
    std::cout << "=== Precision Timer Examples ===" << std::endl;
    
    {
        PrecisionTimer timer("TestFunction1");
        TestFunction1();
    }
    
    std::cout << std::endl;
    
    {
        PrecisionTimer timer("TestFunction2");
        TestFunction2();
    }
    
    std::cout << std::endl;
    
    // 手动控制计时器
    PrecisionTimer manualTimer("Manual Timer");
    TestFunction1();
    std::cout << "Elapsed so far: " << manualTimer.GetElapsed() << " ms" << std::endl;
    TestFunction2();
    manualTimer.Stop();
    
    return 0;
}

性能基准测试工具

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <iostream>
#include <chrono>
#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>

class Benchmark
{
private:
    std::string m_Name;
    std::vector<long long> m_Results;
    
public:
    Benchmark(const std::string& name) : m_Name(name) {}
    
    template<typename Func>
    void Run(Func&& func, int iterations = 1)
    {
        m_Results.clear();
        m_Results.reserve(iterations);
        
        for (int i = 0; i < iterations; ++i)
        {
            auto start = std::chrono::high_resolution_clock::now();
            func();
            auto end = std::chrono::high_resolution_clock::now();
            
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
            m_Results.push_back(duration.count());
        }
    }
    
    void PrintResults() const
    {
        if (m_Results.empty())
        {
            std::cout << m_Name << ": No results" << std::endl;
            return;
        }
        
        // 计算统计信息
        long long total = std::accumulate(m_Results.begin(), m_Results.end(), 0LL);
        double average = static_cast<double>(total) / m_Results.size();
        
        auto minMax = std::minmax_element(m_Results.begin(), m_Results.end());
        long long minTime = *minMax.first;
        long long maxTime = *minMax.second;
        
        // 计算中位数
        std::vector<long long> sorted = m_Results;
        std::sort(sorted.begin(), sorted.end());
        long long median = sorted[sorted.size() / 2];
        
        std::cout << "=== " << m_Name << " Benchmark Results ===" << std::endl;
        std::cout << "Iterations: " << m_Results.size() << std::endl;
        std::cout << "Total time: " << total << " μs" << std::endl;
        std::cout << "Average: " << average << " μs" << std::endl;
        std::cout << "Median: " << median << " μs" << std::endl;
        std::cout << "Min: " << minTime << " μs" << std::endl;
        std::cout << "Max: " << maxTime << " μs" << std::endl;
        std::cout << std::endl;
    }
};

// 测试函数
void VectorPushBack()
{
    std::vector<int> vec;
    for (int i = 0; i < 1000; ++i)
    {
        vec.push_back(i);
    }
}

void VectorReserveAndPushBack()
{
    std::vector<int> vec;
    vec.reserve(1000);
    for (int i = 0; i < 1000; ++i)
    {
        vec.push_back(i);
    }
}

void VectorEmplaceBack()
{
    std::vector<int> vec;
    vec.reserve(1000);
    for (int i = 0; i < 1000; ++i)
    {
        vec.emplace_back(i);
    }
}

int main()
{
    std::cout << "=== Performance Benchmark ===" << std::endl;
    
    const int iterations = 1000;
    
    Benchmark bench1("Vector push_back");
    bench1.Run(VectorPushBack, iterations);
    bench1.PrintResults();
    
    Benchmark bench2("Vector reserve + push_back");
    bench2.Run(VectorReserveAndPushBack, iterations);
    bench2.PrintResults();
    
    Benchmark bench3("Vector reserve + emplace_back");
    bench3.Run(VectorEmplaceBack, iterations);
    bench3.PrintResults();
    
    return 0;
}

不同时钟类型的比较

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <chrono>
#include <thread>

void CompareDifferentClocks()
{
    std::cout << "=== Different Clock Types ===" << std::endl;
    
    // 1. system_clock - 系统时钟,可能会被调整
    auto system_start = std::chrono::system_clock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    auto system_end = std::chrono::system_clock::now();
    auto system_duration = std::chrono::duration_cast<std::chrono::milliseconds>(system_end - system_start);
    
    std::cout << "system_clock duration: " << system_duration.count() << " ms" << std::endl;
    
    // 2. steady_clock - 单调时钟,不会被调整
    auto steady_start = std::chrono::steady_clock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    auto steady_end = std::chrono::steady_clock::now();
    auto steady_duration = std::chrono::duration_cast<std::chrono::milliseconds>(steady_end - steady_start);
    
    std::cout << "steady_clock duration: " << steady_duration.count() << " ms" << std::endl;
    
    // 3. high_resolution_clock - 高精度时钟
    auto hr_start = std::chrono::high_resolution_clock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    auto hr_end = std::chrono::high_resolution_clock::now();
    auto hr_duration = std::chrono::duration_cast<std::chrono::milliseconds>(hr_end - hr_start);
    
    std::cout << "high_resolution_clock duration: " << hr_duration.count() << " ms" << std::endl;
    
    // 时钟精度信息
    std::cout << "\nClock precision information:" << std::endl;
    std::cout << "system_clock period: " << std::chrono::system_clock::period::num 
              << "/" << std::chrono::system_clock::period::den << " seconds" << std::endl;
    std::cout << "steady_clock period: " << std::chrono::steady_clock::period::num 
              << "/" << std::chrono::steady_clock::period::den << " seconds" << std::endl;
    std::cout << "high_resolution_clock period: " << std::chrono::high_resolution_clock::period::num 
              << "/" << std::chrono::high_resolution_clock::period::den << " seconds" << std::endl;
}

int main()
{
    CompareDifferentClocks();
    return 0;
}

实际应用:性能分析器

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <iostream>
#include <chrono>
#include <unordered_map>
#include <string>
#include <iomanip>

class Profiler
{
private:
    struct ProfileData
    {
        long long totalTime = 0;
        int callCount = 0;
        long long minTime = LLONG_MAX;
        long long maxTime = 0;
    };
    
    static std::unordered_map<std::string, ProfileData> s_ProfileData;
    
public:
    class ScopedTimer
    {
    private:
        std::string m_Name;
        std::chrono::time_point<std::chrono::high_resolution_clock> m_StartTime;
        
    public:
        ScopedTimer(const std::string& name) : m_Name(name)
        {
            m_StartTime = std::chrono::high_resolution_clock::now();
        }
        
        ~ScopedTimer()
        {
            auto endTime = std::chrono::high_resolution_clock::now();
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - m_StartTime);
            long long time = duration.count();
            
            auto& data = s_ProfileData[m_Name];
            data.totalTime += time;
            data.callCount++;
            data.minTime = std::min(data.minTime, time);
            data.maxTime = std::max(data.maxTime, time);
        }
    };
    
    static void PrintResults()
    {
        std::cout << "=== Profiler Results ===" << std::endl;
        std::cout << std::left << std::setw(20) << "Function" 
                  << std::setw(10) << "Calls" 
                  << std::setw(15) << "Total (μs)" 
                  << std::setw(15) << "Average (μs)" 
                  << std::setw(12) << "Min (μs)" 
                  << std::setw(12) << "Max (μs)" << std::endl;
        std::cout << std::string(84, '-') << std::endl;
        
        for (const auto& pair : s_ProfileData)
        {
            const auto& data = pair.second;
            double average = static_cast<double>(data.totalTime) / data.callCount;
            
            std::cout << std::left << std::setw(20) << pair.first
                      << std::setw(10) << data.callCount
                      << std::setw(15) << data.totalTime
                      << std::setw(15) << std::fixed << std::setprecision(2) << average
                      << std::setw(12) << data.minTime
                      << std::setw(12) << data.maxTime << std::endl;
        }
    }
    
    static void Clear()
    {
        s_ProfileData.clear();
    }
};

std::unordered_map<std::string, Profiler::ProfileData> Profiler::s_ProfileData;

// 宏定义简化使用
#define PROFILE_SCOPE(name) Profiler::ScopedTimer timer(name)
#define PROFILE_FUNCTION() PROFILE_SCOPE(__FUNCTION__)

// 测试函数
void FastFunction()
{
    PROFILE_FUNCTION();
    
    volatile int sum = 0;
    for (int i = 0; i < 1000; ++i)
    {
        sum += i;
    }
}

void SlowFunction()
{
    PROFILE_FUNCTION();
    
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

void MediumFunction()
{
    PROFILE_FUNCTION();
    
    volatile int sum = 0;
    for (int i = 0; i < 100000; ++i)
    {
        sum += i * i;
    }
}

void ComplexFunction()
{
    PROFILE_SCOPE("ComplexFunction");
    
    {
        PROFILE_SCOPE("ComplexFunction::Part1");
        FastFunction();
    }
    
    {
        PROFILE_SCOPE("ComplexFunction::Part2");
        MediumFunction();
    }
    
    {
        PROFILE_SCOPE("ComplexFunction::Part3");
        SlowFunction();
    }
}

int main()
{
    std::cout << "=== Performance Profiler Example ===" << std::endl;
    
    // 运行测试函数多次
    for (int i = 0; i < 100; ++i)
    {
        FastFunction();
    }
    
    for (int i = 0; i < 50; ++i)
    {
        MediumFunction();
    }
    
    for (int i = 0; i < 10; ++i)
    {
        SlowFunction();
    }
    
    for (int i = 0; i < 5; ++i)
    {
        ComplexFunction();
    }
    
    Profiler::PrintResults();
    
    return 0;
}

时间格式化和转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <chrono>
#include <iomanip>
#include <sstream>

class TimeFormatter
{
public:
    static std::string FormatDuration(std::chrono::nanoseconds duration)
    {
        auto ns = duration.count();
        
        if (ns < 1000)
        {
            return std::to_string(ns) + " ns";
        }
        else if (ns < 1000000)
        {
            return std::to_string(ns / 1000.0) + " μs";
        }
        else if (ns < 1000000000)
        {
            return std::to_string(ns / 1000000.0) + " ms";
        }
        else
        {
            return std::to_string(ns / 1000000000.0) + " s";
        }
    }
    
    static std::string FormatTimePoint(std::chrono::system_clock::time_point tp)
    {
        auto time_t = std::chrono::system_clock::to_time_t(tp);
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
            tp.time_since_epoch()) % 1000;
        
        std::stringstream ss;
        ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S");
        ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
        
        return ss.str();
    }
};

void TimeFormattingExample()
{
    std::cout << "=== Time Formatting Example ===" << std::endl;
    
    auto start = std::chrono::high_resolution_clock::now();
    
    // 模拟一些工作
    std::this_thread::sleep_for(std::chrono::milliseconds(123));
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = end - start;
    
    std::cout << "Duration: " << TimeFormatter::FormatDuration(duration) << std::endl;
    
    // 当前时间
    auto now = std::chrono::system_clock::now();
    std::cout << "Current time: " << TimeFormatter::FormatTimePoint(now) << std::endl;
    
    // 不同精度的时间测量
    std::vector<std::chrono::nanoseconds> durations = {
        std::chrono::nanoseconds(500),
        std::chrono::microseconds(750),
        std::chrono::milliseconds(250),
        std::chrono::seconds(2)
    };
    
    for (const auto& d : durations)
    {
        std::cout << "Formatted: " << TimeFormatter::FormatDuration(d) << std::endl;
    }
}

int main()
{
    TimeFormattingExample();
    return 0;
}

总结

  1. chrono库基础:C++11提供的高精度时间测量库
  2. 时钟类型
    • system_clock:系统时钟,可能被调整
    • steady_clock:单调时钟,适合测量时间间隔
    • high_resolution_clock:高精度时钟
  3. 计时器实现:使用RAII模式自动计时,析构函数输出结果
  4. 性能分析
    • 基准测试工具
    • 性能分析器
    • 统计信息计算
  5. 实际应用
    • 代码性能优化
    • 算法比较
    • 系统监控
  6. 最佳实践
    • 使用steady_clock测量时间间隔
    • 多次测量取平均值
    • 注意编译器优化对测量的影响
updatedupdated2025-09-202025-09-20