C++获取函数运行时间

第一种方法:
GetTickCount()获取系统启动后的时间间隔,精确度有限,跟CPU有关。
第二种方法:

QueryPerformanceCounter()这个函数返回高精确度性能计数器的值,它可以以us为单位计时.但是它确切的精确计时的最小单位是与系统有关的,所以,必须要查询系统以得到QueryPerformanceCounter()返回的嘀哒声的频率.

QueryPerformanceFrequency()提供了这个频率值,返回每秒嘀哒声的个数.

有了两个函数,可以将其封装在一个Time类中,从创建对象开始计时,直至对象销毁。

class Time {
public:
    Time() {
        QueryPerformanceFrequency(&nFreq);
        QueryPerformanceCounter(&nBeginTime);//开始计时  
    }
    ~Time()
    {
        QueryPerformanceCounter(&nEndTime);//停止计时  
        time = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) / (double)nFreq.QuadPart;//计算程序执行时间单位为s  
        cout << "程序执行时间:" << time * 1000 << "ms" << endl;
    }
private:
    LARGE_INTEGER nFreq;
    LARGE_INTEGER nBeginTime;
    LARGE_INTEGER nEndTime;
    double time = 0;
};
void Test()
{
    Time t;
    for (int i = 0; i < 1000000; i++)
    {
    }
}
int main() {
    Test();
}

方法三:

在Linux下可用。
RDTSC指令,在Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述几种方法所无法比拟的.在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31

#if defined (__i386__)
static __inline__ unsigned long long GetCycleCount(void)
{
        unsigned long long int x;
        __asm__ volatile("rdtsc":"=A"(x));
        return x;
}
#elif defined (__x86_64__)
static __inline__ unsigned long long GetCycleCount(void)
{
        unsigned hi,lo;
        __asm__ volatile("rdtsc":"=a"(lo),"=d"(hi));
        return ((unsigned long long)lo)|(((unsigned long long)hi)<<32);
}
#endif

void test8()
{
        unsigned long t1,t2;
        t1 = (unsigned long)GetCycleCount();
        foo();//dosomething
        t2 = (unsigned long)GetCycleCount();
        printf("Use Time:%f\n",(t2 - t1)*1.0/FREQUENCY); //FREQUENCY  CPU的频率
}
<think>好的,用户想在Qt C++中记录函数运行时间。根据之前的回答和用户提供的引用,我需要综合几种方法来解决这个问题。 首先,用户提到了引用[2]中的clock()方法。虽然这种方法简单,但可能不够精确,尤其是在多线程或高精度需求的情况下。不过对于一般的性能测试,这应该足够。我需要解释如何在Qt中使用这种方法,同时注意跨平台的问题,比如Windows和Linux的不同实现。 然后,Qt自带的QElapsedTimer类可能更合适,因为它专门为高精度计时设计,并且跨平台兼容性好。用户可能没有意识到这个类的存在,所以需要详细介绍其用法,包括如何开始计时、获取经过的时间,以及不同时钟类型的区别。 另外,用户之前的问题涉及到防止Segmentation Fault,所以在示例代码中需要注意对象生命周期管理,比如使用父对象来自动释放内存,避免野指针问题。比如在QTimer的例子中,指定父对象来确保计时器在正确的作用域内被管理。 用户可能还需要多线程环境下的计时方法,但当前问题中没有明确提到。不过考虑到Qt常用于多线程应用,可能需要提到QElapsedTimer在多线程中的使用注意事项,比如线程安全和时钟类型的选择。 此外,引用[3]提到了C++调用Python的情况,虽然当前问题不直接相关,但用户可能有跨语言集成的需求,未来可能需要扩展。但这次暂时不需要涉及。 用户可能希望代码示例能够直接集成到他们的Qt项目中,所以需要提供完整的类示例,比如在按钮点击时记录函数时间,并展示如何输出结果到调试窗口或日志。结合引用[1]中的日志记录方法,可以将时间信息写入运行日志,方便后续分析。 需要注意Qt的信号槽连接方式,确保计时逻辑正确嵌入到槽函数中,避免因连接错误导致的计时不准确或程序崩溃。比如使用lambda表达式时,要正确捕获变量,并管理好生命周期。 最后,总结不同方法的适用场景,帮助用户根据具体需求选择合适的方法。比如QElapsedTimer适用于高精度需求,而clock()适用于简单场景,C++11的chrono库则提供了现代且跨平台的解决方案。</think>### 在Qt/C++中记录函数运行时间的实现方法 #### 一、Qt原生高精度计时方案 ##### 方法1:QElapsedTimer(推荐方案) ```cpp #include <QElapsedTimer> void MyClass::criticalFunction() { QElapsedTimer timer; timer.start(); // 启动计时[^2] // 待测函数代码 performComplexCalculation(); qint64 elapsedNs = timer.nsecsElapsed(); // 纳秒级精度 qDebug() << "耗时:" << elapsedNs / 1e6 << "ms"; } ``` ##### 方法2:结合QTimer的统计方法 ```cpp QTimer m_perfTimer; int m_executionCount = 0; double m_totalTime = 0; void MyClass::startMeasurement() { connect(&m_perfTimer, &QTimer::timeout, [=](){ double avgTime = m_totalTime / m_executionCount; WRITE_LOG->WriteRunLog(QString("平均耗时:%1 ms").arg(avgTime)); // 结合日志系统[^1] }); m_perfTimer.start(5000); // 每5秒输出统计结果 } void monitoredFunction() { QElapsedTimer timer; timer.start(); // 业务逻辑代码 processData(); m_totalTime += timer.elapsed(); // 毫秒级精度 m_executionCount++; } ``` #### 二、标准C++计时方案 ##### 方法1:C++11 chrono库(跨平台推荐) ```cpp #include <chrono> void measureRuntime() { auto start = std::chrono::high_resolution_clock::now(); optimizedAlgorithm(); // 被测函数 auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); qDebug() << "耗时:" << duration.count() << "μs"; } ``` ##### 方法2:传统clock()方法(适用简单场景) ```cpp #include <ctime> void legacyMeasurement() { clock_t start = clock(); legacyFunction(); // 传统函数 clock_t end = clock(); double elapsed = double(end - start) / CLOCKS_PER_SEC * 1000; // 转换为毫秒[^2] WRITE_LOG->WriteRunLog(QString("耗时:%1 ms").arg(elapsed)); // 写入运行日志[^1] } ``` #### 三、多线程安全实现方案 ```cpp class ThreadSafeTimer : public QObject { Q_OBJECT public: explicit ThreadSafeTimer(QObject* parent = nullptr) : QObject(parent), m_timer(new QElapsedTimer) {} void startMeasurement() { QMutexLocker locker(&m_mutex); m_timer->start(); } double getElapsed() { QMutexLocker locker(&m_mutex); return m_timer->elapsed() / 1000.0; } private: QScopedPointer<QElapsedTimer> m_timer; QMutex m_mutex; }; // 使用示例 void workerThreadTask(ThreadSafeTimer* timer) { timer->startMeasurement(); performThreadWork(); qDebug() << "线程任务耗时:" << timer->getElapsed() << "秒"; } ``` #### 四、最佳实践指南 1. **精度选择原则** - 微秒级需求:使用`QElapsedTimer::nsecsElapsed()`或C++11 chrono - 毫秒级需求:`QElapsedTimer::elapsed()` - 秒级需求:`clock()`或`QTime::elapsed()` 2. **结果输出规范** ```cpp void outputMeasurement(qint64 elapsed) { QString msg = QString("[%1] %2 耗时 %3ms") .arg(QDateTime::currentDateTime().toString("hh:mm:ss.zzz")) .arg(__FUNCTION__) .arg(elapsed); qDebug() << msg; WRITE_LOG->WriteRunLog(msg); // 集成日志系统[^1] } ``` 3. **热区分析技巧** ```cpp #define MEASURE_SCOPE(name) QElapsedTimer _timer##__LINE__; _timer##__LINE__.start(); \ QSharedPointer<QElapsedTimer> _scopeTimer(new QElapsedTimer(_timer##__LINE__), [name](QElapsedTimer* t){ qDebug() << name << "耗时:" << t->elapsed() << "ms"; }); void analyzedFunction() { MEASURE_SCOPE("数据库操作"); performDatabaseQuery(); } ``` #### 五、调试与优化建议 1. **Valgrind性能分析(引用[2]扩展)** ```bash valgrind --tool=callgrind ./your_qt_app kcachegrind callgrind.out.* ``` 2. **Qt Creator内置分析器** - 使用「分析」菜单中的QML Profiler/C++ Profiler - 查看函数调用热图和时间分布 3. **发布模式测量注意事项** ```qmake # 在.pro文件中添加 QMAKE_CXXFLAGS_RELEASE -= -O2 QMAKE_CXXFLAGS_RELEASE += -O0 # 关闭优化进行准确测量 ``` --- ### 选择建议表格 | 场景 | 推荐方案 | 精度 | 线程安全 | |------|----------|------|----------| | 单次函数测量 | QElapsedTimer | 1ns | 是 | | 长期统计 | C++11 chrono | 1μs | 是 | | 跨平台需求 | std::chrono | 1ns | 是 | | 简单调试 | clock() | 1ms | 否 | --- ### 典型错误示例 ```cpp // 错误:未考虑编译器优化 void unreliableMeasurement() { QTime t; t.start(); for(int i=0; i<1000000; ++i) {} // 空循环可能被优化 qDebug() << t.elapsed(); // 可能输出0ms } // 正确:阻止编译器优化 void reliableTest() { volatile int dummy = 0; // 使用volatile防止优化 QElapsedTimer timer; timer.start(); for(int i=0; i<1000000; ++i) { ++dummy; } qDebug() << timer.elapsed(); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值