使用计时器来测量代码性能
来源:互联网 发布:网络聊天技巧知乎 编辑:程序博客网 时间:2024/06/06 07:29
在性能优化的时候,我们首先要做的是确定优化目标,即要定位最耗时的代码段 (在之前需要做架构和设计方案的优化,只有先确保房子盖的坚固没问题,才去考虑装修的事)。通常的做法就是加一些计时代码来测量代码的执行时间,看是否符合预期。那么本文就介绍一些与计时相关的一些知识。
可用的计时方法
- 汇编指令RDTSC
- GetTickCount()
- timeGetTime()
- QueryPerformanceCount()
关于RDTSC指令
- Intel Pentium系列以后的所有处理器中都包含一个64 bit的寄存器TSC, 该寄存器保存CPU重置后经过的指令周期数。而RDTSC指令就是用来读取该寄存器值,通过EDX:EAX返回。并不是所有的处理器都包含该寄存器,如Cyrix 6x86。在Linux下,如果/proc/cpuinfo包含rdtscp,那么处理器支持TSC。
- 当代码运行在多核或支持超线程的处理器环境,或支持休眠的操作系统中时,要小心使用RDTSC指令。因为多CPU下的TSC并不会保持同步,而系统休眠时会改变处理器的工作频率。
- Intel Pentium Pro以后的处理器支持指令重排优化,也就是说RDTSC的执行顺序可能会被改变,从而计算了错误的指令执行时间。为了防止这种情况出现,可以先执行一些序列化指令,如CPUID。
- 在Windows平台中,微软不建议使用TSC作为高精度的计时器,建议使用QueryPerformanceCounter()和QueryPerformanceFrequency()。Linux平台下有类似的函数,clock_gettime(CLOCK_MONOTONIC).
UINT64 readtsc(void) {#if defined(__GNUC__)# if defined(__i386__) uint64_t x; __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); return x;# elif defined(__x86_64__) uint32_t hi, lo; __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); return ((uint64_t)lo) | ((uint64_t)hi << 32);# else# error Unsupported architecture.# endif#elif defined(_MSC_VER) __asm { return __rdtsc(); }#else# error Other compilers not supported...#endif}
将机器指令周期转换为时间
- 首先要获取CPU的主频,一般忽略因系统休眠而产生的变频问题。在Windows下,可以读取注册表值:HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\N\~MHz,也可直接调用QueryPerformanceFrequency()。在Linux下,可以读取/proc/cpuinfo。
- 时间差 = 指令周期差 / CPU主频
如何精确测量代码的运行时间
- 根据你的需要来选择测量方法,GetTickCount()和timeGetTime()提供ms级精度,但是它们比RDTSC和QueryPerformanceCount()更稳定。
- 减少代码被中断的机会:尽量减少需要测量的代码量(减少线程被切换的机会);尽量减小需要访问的内存(缓存命中、缺页、内存对齐等都会影响运行时间变化);提高线程优先级;
- Cache warming: 将数据和指令提前放入缓存。
- 多次测量取最小值。
- QueryPerformanceCounter()使用多种方式来获取时间计数值,如在单处理器Intel平台中可能由RDTSC实现,其它平台下也可能通过专用的高精度硬件计时器。因此,QueryPerformanceCounter()本身的调用开销相对于RDTSC指令要高昂的多,在一些较小任务的计时操作时不得不考虑该因素。此外,在多处理器平台中,建议通过SetThreadAffinityMask()来限制线程的执行处理器,从而克服多处理器的时钟不同步问题。但是,SetThreadAffinityMask()会极大的影响系统的调度策略,一般会对性能造成影响,此时可以考虑SetThreadIdealProcessor().
推荐阅读
- Time Stamp Counter
- Using the RDTSC Instruction for Performance Monitoring
- How to Benchmark Code Execution Times on Intel IA-32 and IA-64 Instruction Set Architectures
- 多核时代不宜再用x86的RDTSC指令测试指令周期和时间
- Performance measurements with RDTSC
- Windows下遇到测量代码性能问题
- Game Timing and Multicore Processors
- 使用计时器来测量代码性能
- 怎么使用iperf来测量wifi吞吐量
- 你都使用哪些工具来测试代码的性能?
- 【Cocos2dx】计时器的使用,计时器的嵌套,与在计时器中延时执行一段代码
- Unity-只使用一个计时器来实现多波怪的生成
- C# 使用Stopwatch监视计时器来计算函数执行时间
- 性能测量指标
- 性能测量工具备忘
- netperf 网络性能测量
- python3 性能测量
- CUDA2.3-原理之任意长度的矢量求和与用事件来测量性能
- 使用 ContentProviderOperation 来提升性能
- 使用 ContentProviderOperation 来提升性能
- 使用 ContentProviderOperation 来提升性能
- 使用 ContentProviderOperation 来提升性能
- ASP.NET 中使用计时器执行用户代码
- (亲测)安卓计时器demo+代码+Chronometer的使用
- 如何使用VSTS工具来分析软件的代码和性能?
- Android网络连接网络
- 移动广告商点评--多盟
- [Android实例] Android开发 API人脸检测实例教程(内含源码)
- FORM中诡异的VALIDATE事件
- c/c++ 获取文件的属性
- 使用计时器来测量代码性能
- Oracle ebs form when-validate-record
- 基于IMD的包过滤防火墙原理与实现
- 解决android textview自动换行问题
- 常用正则表达式(收集)
- 发两句牢骚
- NSBundle
- 一些.NET开源测试工具简介(来自开源中国)
- asp.net 读写xml文件示例代码