c++计时器类

一、Windows 专用

以下实现高精度(支持微秒/纳秒)、带 ID 管理、可同时测多个计时器的 C++ 类。

  • 开始计时
  • 结束计时
  • 按 ID 区分多个计时器
  • 获取时间(微秒 / 纳秒)
  • 按 ID 顺序打印所有已测时间
  • Windows 高精度 QueryPerformanceCounter

代码块

cpp 复制代码
#include <Windows.h>
#include <iostream>
#include <vector>
#include <unordered_map>

class HighResolutionTimer
{
private:
    // 单个计时器的数据结构
    struct TimerData
    {
        LARGE_INTEGER start;
        LARGE_INTEGER end;
        bool isRunning = false;
        bool hasFinished = false;
    };

    LARGE_INTEGER m_freq;                          // 系统时钟频率
    std::unordered_map<int, TimerData> m_timers;   // 按 ID 存储计时器
    std::vector<int> m_idOrder;                     // 记录 ID 顺序(保证打印顺序)

public:
    // 构造函数:初始化高精度时钟
    HighResolutionTimer()
    {
        QueryPerformanceFrequency(&m_freq);
    }

    // ====================== 开始计时(指定ID) ======================
    void start(int id)
    {
        // 如果是新ID,记录顺序
        if (m_timers.find(id) == m_timers.end())
        {
            m_idOrder.push_back(id);
        }

        auto& timer = m_timers[id];
        QueryPerformanceCounter(&timer.start);
        timer.isRunning = true;
        timer.hasFinished = false;
    }

    // ====================== 结束计时(指定ID) ======================
    void stop(int id)
    {
        if (m_timers.find(id) == m_timers.end())
        {
            std::cerr << "ID " << id << " 未开始计时!" << std::endl;
            return;
        }

        auto& timer = m_timers[id];
        if (!timer.isRunning)
        {
            std::cerr << "ID " << id << " 未在运行中!" << std::endl;
            return;
        }

        QueryPerformanceCounter(&timer.end);
        timer.isRunning = false;
        timer.hasFinished = true;
    }

    // ====================== 获取时间:微秒 us ======================
    long long getElapsedMicroseconds(int id)
    {
        if (!isValid(id)) return -1;

        auto& t = m_timers[id];
        return (t.end.QuadPart - t.start.QuadPart) * 1000000LL / m_freq.QuadPart;
    }

    // ====================== 获取时间:纳秒 ns ======================
    long long getElapsedNanoseconds(int id)
    {
        if (!isValid(id)) return -1;

        auto& t = m_timers[id];
        return (t.end.QuadPart - t.start.QuadPart) * 1000000000LL / m_freq.QuadPart;
    }

    // ====================== 按ID顺序打印所有结果 ======================
    void printAll()
    {
        std::cout << "\n======= 所有计时器结果(按ID顺序)=======\n";
        for (int id : m_idOrder)
        {
            if (!m_timers[id].hasFinished)
            {
                std::cout << "ID " << id << ":未完成\n";
                continue;
            }

            auto us = getElapsedMicroseconds(id);
            auto ns = getElapsedNanoseconds(id);

            std::cout << "ID " << id
                << " | 耗时: " << us << " us (" << ns << " ns)\n";
        }
        std::cout << "=========================================\n\n";
    }

    // 清空所有计时器
    void clear()
    {
        m_timers.clear();
        m_idOrder.clear();
    }

private:
    bool isValid(int id)
    {
        if (m_timers.find(id) == m_timers.end())
        {
            std::cerr << "ID " << id << " 不存在!" << std::endl;
            return false;
        }
        if (!m_timers[id].hasFinished)
        {
            std::cerr << "ID " << id << " 未停止!" << std::endl;
            return false;
        }
        return true;
    }
};

使用示例

cpp 复制代码
int main()
{
    HighResolutionTimer timer;

    // 同时测多个任务
    timer.start(1);
    // 你的代码...
    timer.stop(1);

    timer.start(2);
    // 你的代码...
    timer.stop(2);

    timer.start(10);
    // 你的代码...
    timer.stop(10);

    // 获取单个时间
    auto us = timer.getElapsedMicroseconds(1);
    auto ns = timer.getElapsedNanoseconds(1);

    // 一键打印所有(按你 start 的顺序)
    timer.printAll();

    return 0;
}

输出效果

复制代码
======= 所有计时器结果(按ID顺序)=======
ID 1 | 耗时: 12 us (12543 ns)
ID 2 | 耗时: 84 us (84120 ns)
ID 10 | 耗时: 421 us (421340 ns)
=========================================

二、多平台通用

以下为跨平台(Windows + Linux + macOS)、线程安全、高精度计时、自动保存日志、支持多ID管理的 C++ 计时器类。

  • 多线程安全
  • 支持多 ID 同时计时
  • start(id) / stop(id)
  • getUs(id) / getNs(id)
  • printAll() 按顺序打印
  • 自动写日志文件(timer_log.txt)
  • 跨平台兼容(Windows/Linux/macOS)
  • 微秒、纳秒精度
  • 无第三方依赖,C++11 及以上即可

代码块

cpp 复制代码
#include <iostream>
#include <vector>
#include <unordered_map>
#include <mutex>
#include <fstream>
#include <chrono>
#include <string>

#ifdef _WIN32
#include <windows.h>
#endif

using namespace std;
using namespace chrono;

class HighResolutionTimer
{
private:
    struct TimerRecord
    {
        time_point<high_resolution_clock> start;
        time_point<high_resolution_clock> end;
        bool running = false;
        bool finished = false;
    };

    unordered_map<int, TimerRecord> m_records;
    vector<int> m_id_order;
    mutex m_mutex;                  // 线程安全
    ofstream m_log_file;            // 日志文件

public:
    HighResolutionTimer()
    {
        // 自动打开日志
        m_log_file.open("timer_log.txt", ios::out | ios::app);
    }

    ~HighResolutionTimer()
    {
        if (m_log_file.is_open())
            m_log_file.close();
    }

    // ===================== 开始计时 =====================
    void start(int id)
    {
        lock_guard<mutex> lock(m_mutex);

        if (m_records.find(id) == m_records.end())
            m_id_order.push_back(id);

        auto& rec = m_records[id];
        rec.start = high_resolution_clock::now();
        rec.running = true;
        rec.finished = false;
    }

    // ===================== 停止计时 =====================
    void stop(int id)
    {
        lock_guard<mutex> lock(m_mutex);

        if (m_records.find(id) == m_records.end())
            return;

        auto& rec = m_records[id];
        if (!rec.running)
            return;

        rec.end = high_resolution_clock::now();
        rec.running = false;
        rec.finished = true;

        // 自动写入日志
        writeLog(id);
    }

    // ===================== 获取微秒 =====================
    long long getUs(int id)
    {
        lock_guard<mutex> lock(m_mutex);
        if (!valid(id)) return -1;
        auto& r = m_records[id];
        return duration_cast<microseconds>(r.end - r.start).count();
    }

    // ===================== 获取纳秒 =====================
    long long getNs(int id)
    {
        lock_guard<mutex> lock(m_mutex);
        if (!valid(id)) return -1;
        auto& r = m_records[id];
        return duration_cast<nanoseconds>(r.end - r.start).count();
    }

    // ===================== 打印所有(按ID顺序) =====================
    void printAll()
    {
        lock_guard<mutex> lock(m_mutex);

        cout << "\n======= 计时器结果(按启动顺序) =======\n";
        for (int id : m_id_order)
        {
            auto& r = m_records[id];
            if (!r.finished)
            {
                cout << "ID " << id << ":未完成\n";
                continue;
            }

            long long us = getUs(id);
            long long ns = getNs(id);
            cout << "ID " << id
                 << " | " << us << " us (" << ns << " ns)\n";
        }
        cout << "========================================\n\n";
    }

    // 清空所有记录
    void clear()
    {
        lock_guard<mutex> lock(m_mutex);
        m_records.clear();
        m_id_order.clear();
    }

private:
    bool valid(int id)
    {
        if (m_records.find(id) == m_records.end()) return false;
        if (!m_records[id].finished) return false;
        return true;
    }

    // ===================== 自动写日志 =====================
    void writeLog(int id)
    {
        if (!m_log_file.is_open()) return;

        auto& r = m_records[id];
        long long us = duration_cast<microseconds>(r.end - r.start).count();
        long long ns = duration_cast<nanoseconds>(r.end - r.start).count();

        m_log_file << "[TIMER] ID=" << id
                   << " | time=" << us << " us (" << ns << " ns)\n";
        m_log_file.flush();
    }
};

使用示例

cpp 复制代码
#include <thread>

void testTask(HighResolutionTimer& timer, int id)
{
    timer.start(id);
    // 模拟你的代码运行
    for (int i = 0; i < 1000000; i++);
    timer.stop(id);
}

int main()
{
    HighResolutionTimer timer;

    timer.start(1);
    // do something...
    timer.stop(1);

    timer.start(2);
    // do something...
    timer.stop(2);

    // 多线程测试
    thread t1(testTask, ref(timer), 10);
    thread t2(testTask, ref(timer), 11);
    t1.join();
    t2.join();

    timer.printAll();
    return 0;
}

日志文件示例(自动生成)

复制代码
[TIMER] ID=1 | time=12 us (12543 ns)
[TIMER] ID=2 | time=84 us (84120 ns)
[TIMER] ID=10 | time=421 us (421340 ns)

三、多平台+名称区分

日志自动按天分文件 + 带时间戳、 不用 int ID,改用 std::string 名称区分定时器类

代码块

cpp 复制代码
#include <iostream>
#include <vector>
#include <unordered_map>
#include <mutex>
#include <fstream>
#include <chrono>
#include <string>
#include <iomanip>
#include <ctime>

using namespace std;
using namespace chrono;

class HighResolutionTimer
{
private:
    struct TimerRecord
    {
        time_point<high_resolution_clock> start;
        time_point<high_resolution_clock> end;
        bool running = false;
        bool finished = false;
    };

    unordered_map<string, TimerRecord> m_records;
    vector<string>          m_name_order;  // 按名称创建顺序保存
    mutex                   m_mutex;
    ofstream                m_log_file;
    string                  m_current_date;

public:
    HighResolutionTimer() {
        updateLogFile();
    }

    ~HighResolutionTimer() {
        if (m_log_file.is_open())
            m_log_file.close();
    }

    // ===================== 开始计时(string 名称) =====================
    void start(const string& name)
    {
        lock_guard<mutex> lock(m_mutex);

        if (m_records.find(name) == m_records.end())
            m_name_order.push_back(name);

        auto& rec = m_records[name];
        rec.start = high_resolution_clock::now();
        rec.running = true;
        rec.finished = false;
    }

    // ===================== 停止计时 =====================
    void stop(const string& name)
    {
        lock_guard<mutex> lock(m_mutex);

        if (m_records.find(name) == m_records.end())
            return;

        auto& rec = m_records[name];
        if (!rec.running)
            return;

        rec.end = high_resolution_clock::now();
        rec.running = false;
        rec.finished = true;

        writeLog(name);
    }

    // ===================== 获取微秒 =====================
    long long getUs(const string& name)
    {
        lock_guard<mutex> lock(m_mutex);
        if (!valid(name)) return -1;
        auto& r = m_records[name];
        return duration_cast<microseconds>(r.end - r.start).count();
    }

    // ===================== 获取纳秒 =====================
    long long getNs(const string& name)
    {
        lock_guard<mutex> lock(m_mutex);
        if (!valid(name)) return -1;
        auto& r = m_records[name];
        return duration_cast<nanoseconds>(r.end - r.start).count();
    }

    // ===================== 打印所有(按创建顺序) =====================
    void printAll()
    {
        lock_guard<mutex> lock(m_mutex);

        cout << "\n======= 计时器结果 =======\n";
        for (auto& name : m_name_order)
        {
            auto& r = m_records[name];
            if (!r.finished) {
                cout << name << ":未完成\n";
                continue;
            }
            cout << name << " | "
                 << getUs(name) << " us ("
                 << getNs(name) << " ns)\n";
        }
        cout << "==========================\n\n";
    }

    void clear()
    {
        lock_guard<mutex> lock(m_mutex);
        m_records.clear();
        m_name_order.clear();
    }

private:
    bool valid(const string& name)
    {
        if (m_records.find(name) == m_records.end()) return false;
        if (!m_records[name].finished) return false;
        return true;
    }

    // ===================== 获取当前日期 YYYYMMDD =====================
    string getCurrentDate()
    {
        auto now = time(nullptr);
        tm tm_time{};
#ifdef _WIN32
        localtime_s(&tm_time, &now);
#else
        localtime_r(&now, &tm_time);
#endif
        ostringstream oss;
        oss << put_time(&tm_time, "%Y%m%d");
        return oss.str();
    }

    // ===================== 获取时间戳 YYYY-MM-DD HH:MM:SS =====================
    string getTimestamp()
    {
        auto now = time(nullptr);
        tm tm_time{};
#ifdef _WIN32
        localtime_s(&tm_time, &now);
#else
        localtime_r(&now, &tm_time);
#endif
        ostringstream oss;
        oss << put_time(&tm_time, "%Y-%m-%d %H:%M:%S");
        return oss.str();
    }

    // ===================== 自动切换日期文件 =====================
    void updateLogFile()
    {
        string today = getCurrentDate();
        if (today == m_current_date && m_log_file.is_open())
            return;

        if (m_log_file.is_open())
            m_log_file.close();

        m_current_date = today;
        string filename = "timer_" + today + ".log";
        m_log_file.open(filename, ios::app | ios::out);
        m_log_file << "=====================================\n";
        m_log_file << "日志开始:" << getTimestamp() << "\n";
        m_log_file << "=====================================\n\n";
    }

    // ===================== 写日志(带时间戳 + 自动切分文件) =====================
    void writeLog(const string& name)
    {
        lock_guard<mutex> lock(m_mutex);
        updateLogFile();

        auto& r = m_records[name];
        long long us = duration_cast<microseconds>(r.end - r.start).count();
        long long ns = duration_cast<nanoseconds>(r.end - r.start).count();

        m_log_file << "[" << getTimestamp() << "] "
                   << "NAME: " << setw(20) << left << name
                   << " | " << us << " us (" << ns << " ns)\n";
        m_log_file.flush();
    }
};

使用示例

cpp 复制代码
#include <thread>

void testFunc(HighResolutionTimer& timer, const string& name)
{
    timer.start(name);
    // 你的业务代码
    for (int i = 0; i < 1000000; i++);
    timer.stop(name);
}

int main()
{
    HighResolutionTimer timer;

    timer.start("数据加载");
    // ...
    timer.stop("数据加载");

    timer.start("图像处理");
    // ...
    timer.stop("图像处理");

    // 多线程也安全
    thread t1(testFunc, ref(timer), "网络请求");
    thread t2(testFunc, ref(timer), "算法计算");
    t1.join();
    t2.join();

    timer.printAll();
    return 0;
}

日志效果

文件名:timer_20260407.log

复制代码
[2026-04-07 22:10:05] NAME: 数据加载     | 12 us (12543 ns)
[2026-04-07 22:10:05] NAME: 图像处理     | 84 us (84120 ns)
[2026-04-07 22:10:05] NAME: 网络请求     | 421 us (421340 ns)
相关推荐
山上三树3 小时前
预处理、编译、汇编、链接详解
c++
2301_789015623 小时前
C++:异常
开发语言·c++·异常·异常的处理方式
CVer儿3 小时前
c++接口内部内存分配问题设计
开发语言·c++
2301_789015623 小时前
C++:智能指针
c语言·开发语言·汇编·c++·智能指针
6Hzlia3 小时前
【Hot 100 刷题计划】 LeetCode 74. 搜索二维矩阵 | C++ 二分查找 (一维展开法)
c++·leetcode·矩阵
a里啊里啊3 小时前
常见面试题目集合
linux·数据库·c++·面试·职场和发展·操作系统
不想写代码的星星3 小时前
C++ 类型擦除:你对象是 Circle 还是 int 不重要,能 draw() 就行,我不挑
c++
是天创呀3 小时前
C++ 类核心知识总结
c++
鲸渔3 小时前
【C++ 基本数据类型】整型、浮点型、字符型、布尔型及大小
开发语言·c++