windows计时介绍
简介:
windows提供了QueryPerformanceCounter (QPC)接口来获取高精度的时间戳或者是测量时间间隔。
QPC不依赖于外部的时钟源,也不与外部的时钟源进行同步。
时间戳和时间间隔经常用于性能度量、延迟度量,这些测量都不依赖于外部的事件参考(应该指的是不依赖于NTP这些,这与timegetofday之类的不同)
如果在同一台机器上测试事件间隔,那么应该使用QPC,如果在多台机器见测量,那么应该使用GetSystemTimePreciseAsFileTime接口,并且在这些机器上使用NTP同步时间。相对于其他接口来说,QPC接口可以帮助你减少获取时间的困难,例如直接读取CPU的tsc(可能是因为tsc因为没有恒定的频率导致有时候不牢靠,甚至是不支持tsc)。
windows版本对于QPC的支持:
Windows XP and Windows 2000: 它可能有些缺陷,比如多核之间的tsc同步,不牢靠的频率等。这可能导致不同核之间独处的时间戳不一致。
Windows Vista and Windows Server 2008:他们使用platform counter(HPET)或APCI power manager Timer作为QPC的基础。这些platform timer(平台性的定时器,多个核公用)在访问的时候延迟比tsc要大,如果多个核同时对它进行访问,那么它会有延迟,所以这限制了它的可测量性。
Windows 7 and Windows Server 2008 R2:win7和windows 2008r2一般都有多核,并且这些核上都有稳定的tsc,所以他们使用tsc作为QPC的基础,tsc访问速度非常快,只要10-100个指令周期。它的消耗比platform counter有很显著的降低。而且并发没有额外的开销,甚至可以通过拥护态直接去读取。 在那些tsc不适合作为计时设备的系统中,系统将会自动的选择平台计数器(hpet或acpi pm)
Windows 8, Windows 8.1, Windows Server 2012, and Windows Server 2012 R2:这些系统都用tsc。
Guidance for acquiring time stamps
windows将持续的投入提供高精度的性能测量。当你需要1微秒或是更高精度的时候,你不需要借助于外部的时钟源,使用QPC就好了。当你需要支持1微秒的UTC同步的时间戳的时候,使用GetSystemTimePreciseAsFileTime就够了。
在那些相对于比较少的不支持tsc的硬件上,获取高精度时间比较麻烦。如果10-16微秒能满足的话,那么就使用GetTickCount64, QueryInterruptTime,QueryUnbiasedInterruptTime接口把。他们是不基于外部时间的。
在具有多个时钟域且硬件未同步的大型服务器系统上使用性能计数器时,Windows会确定TSC不能用于计时目的,并选择平台计数器作为QPC的基础。 虽然此方案仍会产生可靠的时间戳,但访问延迟和可伸缩性会受到不利影响。 因此,如前面的使用指南中所述,仅在需要这种分辨率时才使用提供1微秒或更好分辨率的API。 TSC用作多时钟域系统上的QPC的基础,其包括所有处理器时钟域的硬件同步,因为这有效地使它们用作单个时钟域系统。
性能计数器的频率在系统引导时是固定的,并且在所有处理器中都是一致的,因此您只需在应用程序初始化时查询QueryPerformanceFrequency的频率,然后缓存结果。
Direct TSC usage
我们强烈不建议直接使用RDTSC和RDTSCP 去直接读取CPU发寄存器,因为在一些windows版本上这些是不可靠的,因为虚拟机可能迁移,也有可能TSC频率不是恒定不变或不牢靠的。我们支持使用QPC接口。它具有很高的可移植性、一致性。
注意定时器和时间测量的不同。 软件的定时器并不能用于测量时间,它只能用于告知一段时间过去了。
当然,我们可以通过硬件的定时器来测量时间,比如我在硬件定时器上起一个周期性的高精度的软件定时器,这样我根据他的中断嘀嗒来记录系统运行了多久。我想系统的计时都是类似实现的,全局记录一个这样的系统时间,获取时间的时候去读一下它(读的时候需要加锁,所以读的人越多,那么准确性就越是难以保障)
计时还是得用下面类似的代码结构:
LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds; LARGE_INTEGER Frequency; QueryPerformanceFrequency(&Frequency); QueryPerformanceCounter(&StartingTime); // Activity to be timed QueryPerformanceCounter(&EndingTime); ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart; // // We now have the elapsed number of ticks, along with the // number of ticks-per-second. We use these values // to convert to the number of elapsed microseconds. // To guard against loss-of-precision, we convert // to microseconds *before* dividing by ticks-per-second. // ElapsedMicroseconds.QuadPart *= 1000000; ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;
提问
Is QPC accuracy affected by processor frequency changes caused by power management or Turbo Boost technology?
不会,如果系统有恒定的tsc,那么tsc不会受这些干扰。 如果系统没有恒定的tsc,那么系统会自动选择平台型的定时器(hpet或acpi_pm)
Which processors have non-invariant TSCs? How can I check if my system has a non-invariant TSC?
你不需要自己去确认,系统会自己帮你选择。 如果你一定想要确认的话可以使用Coreinfo.exe或cpuid的flag
Does QPC require a kernel transition (system call)?
如果使用TSC的话,那么是不需要的,如果使用hpet或acpi_pm的话,那么是需要的。
绝对时钟和差分时钟
绝对时钟提供准确的时间读数。 它们通常基于协调世界时(UTC),因此它们的准确性部分取决于它们与外部时间参考的同步程度。 差分时钟测量时间间隔,通常不基于外部时间时期。 QPC是差分时钟,不与外部时间纪元或参考同步。 当您使用QPC进行时间间隔测量时,通常会获得比使用绝对时钟得出的时间戳更高的精度。 这是因为同步绝对时钟的时间的过程可能引入相位和频率偏移,这增加了短期时间间隔测量的不确定性。
PM时钟
ACPI计时器(也称为PM时钟)已添加到系统架构中,以提供与处理器速度无关的可靠时间戳。 因为这是此计时器的单一目标,所以它在单个时钟周期内提供时间戳,但它不提供任何其他功能。
HPET定时器
高精度事件定时器(HPET)由英特尔和微软联合开发,以满足多媒体和其他时间敏感应用的时序要求。 自Windows Vista以来,HPET支持一直在Windows中,而Windows 7和Windows 8硬件徽标认证需要在硬件平台上支持HPET。
显然,这个接口是不会用到RTC的,那么首先需要确认视频软件是否用的就是这个接口(应该是的),windows应该不会用那么老旧的RTC。首先考虑让系统使用稳定的TSC,然后是把acpi_pm模拟从qemu移植到内核中去。
另外需要了解多媒体软件与计时之间的关系。
还可以测试HPET。反正cpu都passthrough不能迁移了,直接加上invtsc吧。