C/C++获取时间方法:gettimeofday()

本文对比了使用clock_t和gettimeofday()方法测量程序运行时间的效果。指出clock_t不适用于多线程程序的原因,并介绍了gettimeofday()的具体用法及其实现多线程性能测试的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在用多线程练习程序的时候, 需要测试性能,获取程序的运行时间。
一开始使用的是:
clock_t 类,而且这个用法还很简单如下

int i = 100000000;
clock_t start,finish; //定义开始,结束变量
start = clock();//初始化
while( i-- );
finish = clock();//初始化结束时间
double duration = (double)(finish - start) / CLOCKS_PER_SEC;//转换浮点型
printf( "%lf seconds\n", duration );

这样就可以了,乍一看很合理呀, 程序开始获取,程序结束了获取时间,
但是运行多线程程序的时候,时间并没有减少,甚至还有所增加。
后来查了资料:

发现clock()是程序从启动到函数调用占用CPU的时间。这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数。

我们都知道,多线程程序是把任务分到多个线程上,并行计算。而clock()函数计算的是所有的cpu的时间,这样跟单线程的就没有区别了,因此用这个函数不太理想。
后来可以直接获取两次系统时间来得到运行时间;
这里就使用了 gettimeofday()方法来得到。下面对其做一个简单介绍

函数原型

#include<sys/time.h>
int gettimeofday(struct  timeval*tv,struct  timezone *tz )

这个函数会把时间包装为一个结构体返回。包括秒,微妙,时区等信息.
具体如下:

struct  timeval{
       long  tv_sec;/*秒*/
       long  tv_usec;/*微妙*/
};
struct  timezone{
        int tz_minuteswest;/*和greenwich时间差*/
        int tz_dsttime; 
}

程序实例

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>



int main()
{
    float time_use=0;
    struct timeval start;
    struct timeval end;

    gettimeofday(&start,NULL); //gettimeofday(&start,&tz);结果一样
    printf("start.tv_sec:%d\n",start.tv_sec);
    printf("start.tv_usec:%d\n",start.tv_usec);

    int i = 100000000;
    while(i--);

    gettimeofday(&end,NULL);
    printf("end.tv_sec:%d\n",end.tv_sec);
    printf("end.tv_usec:%d\n",end.tv_usec);

    time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);//微秒
    printf("time_use is %.10f\n",time_use);
}

通过这个函数即可 准确获取多线程序运行时间。
或者直接写个shell脚本执行时间也可以

### 实现毫秒、微秒或纳秒级别系统时间差计算 在C/C++中,可以利用标准库中的`<chrono>`头文件以及POSIX定义的结构体来实现毫秒、微秒甚至纳秒级别的系统时间差计算。以下是几种常见的方法及其具体实现。 #### 使用 `<chrono>` 头文件 现代C++提供了强大的时间处理工具——`std::chrono`,它支持多种分辨率的时间测量。通过该库,能够轻松获取并比较不同粒度的时间戳。 ```cpp #include <iostream> #include <chrono> int main() { auto start = std::chrono::high_resolution_clock::now(); // 开始计时 // 模拟耗时操作 volatile int i = 0; while (i++ < 1e8); auto end = std::chrono::high_resolution_clock::now(); // 结束计时 // 计算时间差 std::chrono::duration<double, std::milli> duration_ms = end - start; // 毫秒 std::chrono::duration<double, std::micro> duration_us = end - start; // 微秒 std::chrono::duration<double, std::nano> duration_ns = end - start; // 纳秒 std::cout << "Duration in milliseconds: " << duration_ms.count() << " ms\n"; std::cout << "Duration in microseconds: " << duration_us.count() << " us\n"; std::cout << "Duration in nanoseconds: " << duration_ns.count() << " ns\n"; return 0; } ``` 这种方法基于高精度时钟[^1],适用于跨平台开发场景,并能提供较高的时间分辨率。 --- #### 使用 `gettimeofday()` 函数(Linux/Unix) 在POSIX兼容的操作系统上,可以通过调用`gettimeofday()`函数获取当前时间和日期信息。此函数返回的是自UNIX纪元以来经过的秒数和微秒数。 ```cpp #include <sys/time.h> #include <stdio.h> void getTimeDifference(struct timeval& startTime, struct timeval& endTime) { double elapsedTimeUs = (endTime.tv_sec - startTime.tv_sec) * 1e6 + (endTime.tv_usec - startTime.tv_usec); printf("Elapsed Time: %.6f μs\n", elapsedTimeUs); // 输出微秒级时间差 } int main() { struct timeval tStart, tEnd; gettimeofday(&tStart, NULL); // 获取起始时间 // 模拟耗时操作 volatile int i = 0; while (i++ < 1e7); gettimeofday(&tEnd, NULL); // 获取结束时间 getTimeDifference(tStart, tEnd); // 打印时间差 return 0; } ``` 这里需要注意,在某些情况下,`tv_usec`字段可能会溢出,因此需要特别小心处理边界条件[^2]。 --- #### Windows 平台下的 `QueryPerformanceCounter` Windows API 提供了一个高性能计数器接口——`QueryPerformanceCounter`,它可以用来精确地记录短时间段内的流逝时间。 ```cpp #include <windows.h> #include <iostream> double getFrequency() { LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); return static_cast<double>(freq.QuadPart); } double calculateElapsedTime(LARGE_INTEGER start, LARGE_INTEGER end, double frequency) { return ((end.QuadPart - start.QuadPart) / frequency) * 1e9; // 转换为纳秒 } int main() { LARGE_INTEGER startCount, endCount; double frequency = getFrequency(); QueryPerformanceCounter(&startCount); // 开始计时 // 模拟耗时操作 volatile int i = 0; while (i++ < 1e7); QueryPerformanceCounter(&endCount); // 停止计时 double elapsedNs = calculateElapsedTime(startCount, endCount, frequency); std::cout << "Elapsed Time: " << elapsedNs << " ns\n"; // 显示纳秒级时间差 return 0; } ``` 这段代码展示了如何使用硬件性能计数器来达到更高的精度[^4]。 --- #### 利用 CPU TSC 寄存器读取周期数 如果目标机器支持RDTSC指令,则可以直接访问处理器内部的TSC寄存器以获得非常高的频率计数值。不过这种方式依赖于特定架构且不具备可移植性。 ```cpp unsigned __int64 GetCpuCycle(void) { unsigned __int64 cycles; asm volatile ("rdtsc" : "=A"(cycles)); return cycles; } // 测试程序省略... ``` 尽管如此,由于多核环境可能导致不一致的结果,建议仅将其作为实验用途而非生产环境中推荐的做法[^3]。 --- ### 总结 以上介绍了四种不同的技术手段分别针对不同类型的需求进行了阐述。每种方案都有其适用范围与局限之处,请根据实际应用场景选择合适的解决方案。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值