当前位置: 代码网 > it编程>编程语言>C/C++ > 在C++中测量代码执行时间的两种方法

在C++中测量代码执行时间的两种方法

2026年01月07日 C/C++ 我要评论
在c++中,编写代码只是第一步,衡量代码的“效率”同样重要。你如何知道你的 sort 算法比同事写的快?或者你的新功能导致了多少性能下降?你需要一个“秒表&rdqu

在c++中,编写代码只是第一步,衡量代码的“效率”同样重要。你如何知道你的 sort 算法比同事写的快?或者你的新功能导致了多少性能下降?你需要一个“秒表”来精确测量代码的执行时间。

在c++(及c语言)中,你有两种主要的“秒表”:

c 风格 “cpu 秒表” (<ctime>/clock())

  • 比喻: 这是一个老式的“机械秒表”,它只在你的 cpu **真正在为你的程序“工作”(执行指令)**时才会“嘀嗒”。
  • 特点: 它测量的是 cpu 时间 (cpu time)。如果你的程序在“等待”(比如 sleep、等待用户输入或等待网络响应),这个秒表会暂停
  • 精度: 较低,受限于 clocks_per_sec 宏。

现代 c++ 风格 “高精度电子秒表” (<chrono>)

  • 比喻: 这是一个高精度的“电子秒表”,它测量的是墙上时钟 (wall clock) 走过的时间。
  • 特点: 它测量的是真实世界流逝的时间。从你按下“开始”到按下“停止”,无论你的程序是在“工作”还是“等待”,它都在计时。
  • 精度: 极高(通常可以达到纳秒 ns 级别)。
  • 这是现代c++中(c++11及以后)强烈推荐的方式。

在本教程中,你将学会:

  • c 风格 clock():如何使用“cpu 秒表”。
  • c++ std::chrono:如何使用“高精度电子秒表”(推荐!)。
  • 新手的“头号噩梦”cpu 时间 vs 挂钟时间 (wall time) 的致命区别。
  • 实战演练:通过代码对比两种计时器的不同结果。
  • “x光透 视”:用调试器“亲眼目睹”时间点(time_point)对象。

前置知识说明 (100% 自洽):

  • 变量 (variable):理解存储数据的“盒子”,如 double time_taken;
  • 函数 (function):理解可重复使用的“代码积木”。
  • #include:如何包含c++标准库(如 <iostream>, <ctime>, <chrono>)。
  • cout:c++ 中用于在屏幕上打印信息的“扬声器”。
  • 类型转换 (casting):如 double(value),将 value 转换为 double 类型。
  • 编译 (compile):c++代码(“食谱”)必须被“编译”(“烘焙”),才能变成电脑可执行的程序(“蛋糕”)。

第一部分:c 风格clock()(“cpu 秒表”)

clock() 函数在 <ctime> 库中。它返回程序启动到当前时刻为止,cpu 花在你程序上的“嘀嗒数”(clock ticks)。

核心步骤:

  1. 包含 <ctime>
  2. 在代码开始前,调用 clock_t start = clock(); 记录“开始嘀嗒数”。
  3. 在代码结束后,调用 clock_t end = clock(); 记录“结束嘀嗒数”。
  4. 计算差值 double(end - start),然后除以 clocks_per_sec (一个系统常量,表示“每秒多少嘀嗒数”),得到秒数

clock_example.cpp

#include <iostream>
#include <ctime> // 1. 包含 c 时间库
using namespace std;

// 一个耗时的函数 (模拟 cpu 密集型工作)
void heavy_work() {
    // 执行一个(通常会被编译器优化的)空循环来消耗 cpu 时间
    // 在实际测试时,应使用 -o0 (关闭优化) 来观察
    for(long i = 0; i < 3000000000l; ++i) {}
}

int main() {
    cout << "--- 测试 c 风格 <ctime> (clock_t) ---" << endl;
    cout << "每秒“嘀嗒”数 (clocks_per_sec): " << clocks_per_sec << endl;

    // 1. 获取开始时的“cpu嘀嗒数”
    clock_t start = clock();

    // 2. 执行你的代码
    heavy_work();

    // 3. 获取结束时的“cpu嘀嗒数”
    clock_t end = clock();

    // 4. 计算时间差 (秒)
    double cpu_time_taken = double(end - start) / double(clocks_per_sec);

    cout << "cpu 耗时: " << cpu_time_taken << " 秒" << endl;
    
    return 0;
}

“手把手”终端模拟 (结果因机器和编译优化而异):

ps c:\mycode> g++ clock_example.cpp -o clock_example.exe -o0 # -o0 关闭优化
ps c:\mycode> .\clock_example.exe
--- 测试 c 风格 <ctime> (clock_t) ---
每秒“嘀嗒”数 (clocks_per_sec): 1000
cpu 耗时: 1.156 秒

缺点: 精度不高,且无法测量“等待”时间。

第二部分:现代 c++std::chrono(“高精度电子秒表”)

std::chrono 库 (c++11) 是现代c++的黄金标准。它提供了高精度时钟和时间单位(纳秒、微秒、毫秒等)。

核心步骤:

  1. 包含 <chrono>
  2. 使用 auto start = std::chrono::high_resolution_clock::now(); 获取当前挂钟时间点
  3. 使用 auto end = std::chrono::high_resolution_clock::now(); 获取结束时间点
  4. 计算差值:end - start,得到一个 duration (时间段) 对象。
  5. 使用 std::chrono::duration_cast 将这个 duration 对象转换为你想要的单位(如毫秒)。

chrono_example.cpp (推荐用法)

#include <iostream>
#include <chrono> // 1. 包含 c++11 时间库
#include <thread> // 2. 包含线程库 (用来演示“等待”)
using namespace std;

// 使用 using 来简化类型名 (可选,但推荐)
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::duration;
using std::chrono::milliseconds;
using std::chrono::microseconds;

// 耗时函数 (包含工作和等待)
void work_and_sleep() {
    // 模拟 cpu 工作
    for(long i = 0; i < 3000000000l; ++i) {} 

    // 模拟 i/o 等待或休眠 (500毫秒)
    cout << "  (正在休眠 500 毫秒...)" << endl;
    std::this_thread::sleep_for(milliseconds(500));
}

int main() {
    cout << "--- 测试 现代 c++ <chrono> ---" << endl;
    
    // 1. 获取开始时间点
    auto start_time = high_resolution_clock::now();

    // 2. 执行你的代码
    work_and_sleep();

    // 3. 获取结束时间点
    auto end_time = high_resolution_clock::now();

    // 4. 计算时间差
    // 结果是一个 duration 对象
    auto duration_total = duration_cast<milliseconds>(end_time - start_time);
    
    // 5. 打印结果
    cout << "总耗时 (挂钟时间): " << duration_total.count() << " 毫秒" << endl;

    // 也可以转换为其他单位
    auto duration_us = duration_cast<microseconds>(end_time - start_time);
    cout << "  (即 " << duration_us.count() << " 微秒)" << endl;

    return 0;
}

“手把手”终端模拟 (结果因机器而异):

ps c:\mycode> g++ chrono_example.cpp -o chrono_example.exe -std=c++11 -o0 -pthread
ps c:\mycode> .\chrono_example.exe
--- 测试 现代 c++ <chrono> ---
  (正在休眠 500 毫秒...)
总耗时 (挂钟时间): 1658 毫秒
  (即 1658390 微秒)

顿悟时刻: 结果 1658 毫秒,约等于 1158 毫秒 (cpu工作) + 500 毫秒 (休眠)。<chrono> 正确地测量了所有流逝的时间!

第三部分:新手的“头号噩梦”——clock()vs<chrono>

让我们把两个“秒表”放在同一个程序里,测量同一个函数,看看它们的区别。

comparison.cpp (关键对比)

#include <iostream>
#include <ctime>
#include <chrono>
#include <thread>
using namespace std;

// (函数 work_and_sleep 同上)
void work_and_sleep() {
    for(long i = 0; i < 3000000000l; ++i) {} 
    cout << "  (正在休眠 500 毫秒...)" << endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
}

int main() {
    // --- 1. <chrono> 计时 (挂钟时间) ---
    auto start_chrono = std::chrono::high_resolution_clock::now();
    
    // --- 2. <ctime> 计时 (cpu 时间) ---
    clock_t start_clock = clock();

    // --- 3. 执行同一个函数 ---
    cout << "--- 正在执行 work_and_sleep... ---" << endl;
    work_and_sleep();
    cout << "--- 执行完毕 ---" << endl;

    // --- 4. 获取 <ctime> 结果 ---
    clock_t end_clock = clock();
    double cpu_time = double(end_clock - start_clock) / double(clocks_per_sec);
    
    // --- 5. 获取 <chrono> 结果 ---
    auto end_chrono = std::chrono::high_resolution_clock::now();
    auto wall_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end_chrono - start_chrono);

    // --- 6. 打印对比 ---
    cout << "\n--- 结果对比 ---" << endl;
    cout << "cpu 秒表 (clock()): " << cpu_time * 1000 << " 毫秒" << endl;
    cout << "电子秒表 (chrono): " << wall_time_ms.count() << " 毫秒" << endl;

    return 0;
}

“手把手”终端模拟 (结果因机器而异):

ps c:\mycode> g++ comparison.cpp -o comparison.exe -std=c++11 -o0 -pthread
ps c:\mycode> .\comparison.exe
--- 正在执行 work_and_sleep... ---
  (正在休眠 500 毫秒...)
--- 执行完毕 ---

--- 结果对比 ---
cpu 秒表 (clock()): 1162 毫秒 # <-- 只有 cpu 工作的时间!
电子秒表 (chrono): 1663 毫秒 # <-- cpu 工作 (1162) + 休眠 (500)

“黄金法则”:

  • 当你想知道“我的代码占用了多少 cpu 资源?”(用于算法分析),clock() 可以用(但 <chrono> 也有 cpu 时钟)。
  • 当你想知道“用户等了多久?”(从按下按钮到看到结果),永远使用 std::chrono::high_resolution_clock!这几乎是你 99% 情况下想要的答案。

第四部分:“x光透 视”——观察时间点

auto start_time = high_resolution_clock::now(); 返回的对象是一个 time_point(时间点)。它通常只是一个(非常大的)数字,代表从某个“纪 元”(比如1970年1月1日,或计算机启动时)到现在的纳秒数。

“x光”实战(基于chrono_example.cpp)

  1. 设置断点:
    • main 函数的第31行auto start_time = ...之后
    • main 函数的第36行auto end_time = ...之后
  2. 启动调试 (f5)。
  3. 第一次“冻结” (第31行后):
    • 观察“变量”(variables)窗口: 找到 start_time
    • 展开 start_time:你会看到它内部可能有一个成员,比如 _m_time_since_epoch_rep (内部表示)。
    • 你会看到: 一个巨大的数字,例如 1678886400123456789 (纳秒)。
  4. 继续执行 (f5)。
  5. 第二次“冻结” (第36行后):
    • 观察“变量”窗口: 找到 end_time
    • 展开 end_time
    • 你会看到: 另一个巨大的数字,例如 1678886401783456789
  6. (关键!)“监视” (watch) 窗口:
    • 动作: 在“监视”窗口中,添加这个表达式:
      std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count()
    • 你会看到: 1660 (或者你的实际测量值)!
    • 顿悟时刻: 调试器向你展示了 chrono 库是如何通过两个“时间点”相减,得到一个“时间段”,并最终转换为你需要的单位的。

动手试试!(终极挑战:你的“排序分析器”)

现在,你来当一次“算法分析师”。

任务:

  1. “激活” iostream, vector, algorithm (为了 std::sort), chronorandom (为了生成随机数)。
  2. 创建一个非常大vector<int> (例如,1,000,000 个元素),并用随机数字填充它。
  3. 使用 std::chrono(高精度电子秒表):
    • 在调用 std::sort 之前,获取“开始时间”。
    • 调用 std::sort(myvector.begin(), myvector.end());
    • std::sort 之后,获取“结束时间”。
  4. 计算时间差,并以毫秒 (milliseconds) 为单位,打印出排序一百万个随机整数所花费的时间。

sort_timer.cpp (你的 todo):

#include <iostream>
#include <vector>
#include <algorithm> // 需要 std::sort
#include <chrono>    // 需要计时
#include <random>    // 需要随机数
using namespace std;

// (使用 using std::chrono::... 来简化)
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::milliseconds;

int main() {
    // --- 1 & 2: 创建并填充 100 万个随机数 ---
    const int n = 1000000;
    vector<int> numbers;
    numbers.reserve(n); // 预分配内存,提高效率
    
    std::random_device rd;  // 随机数种子源
    std::mt19937 gen(rd()); // 随机数引擎
    std::uniform_int_distribution<> distrib(1, n); // 分布范围
    
    cout << "正在生成 " << n << " 个随机数..." << endl;
    for (int i = 0; i < n; ++i) {
        numbers.push_back(distrib(gen));
    }
    cout << "生成完毕。" << endl;

    // --- todo 3: 计时 ---
    cout << "\n--- 开始排序... ---" << endl;
    
    // auto starttime = ...;
    
    // std::sort(... , ...); // 执行排序
    
    // auto endtime = ...;
    
    // --- todo 4: 计算并打印 ---
    // auto timetaken_ms = ...;
    
    // cout << "排序 " << n << " 个元素耗时: " 
    //      << timetaken_ms.count() << " 毫秒" << endl;

    return 0;
}

这个挑战让你实践了如何使用 std::chrono 来测量一个真实有意义的计算任务(std::sort)的性能。完成它,你就掌握了c++中最重要、最准确的计时工具!

以上就是在c++中测量代码执行时间的两种方法的详细内容,更多关于c++测量代码执行时间的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com