HR定时器精确研究案例

时间:2017-06-22 08:08:05

标签: linux timer linux-kernel drivers

通过这个主题,我将更好地讨论HR计时器和真正的精确度问题。

我研究了很多关于它们的文档,我确信它们是解决Linux内核模块中延迟执行问题的最佳和最可靠的解决方案,CPU成本较低,计时精度更高(例如一些时间关键的驱动程序也使用它们,就像这个https://dev.openwrt.org/browser/trunk/target/linux/generic/files/drivers/pwm/gpio-pwm.c?rev=35328)。

它也适合你吗?

以下是我在此主题上见过的最全面,最详细的文档之一:https://www.landley.net/kdocs/ols/2006/ols2006v1-pages-333-346.pdf

人力资源计时器承诺采用jiffies解决方案,但不幸的是,在我的系统上,我没有得到延迟低于6毫秒的预期结果(我将在稍后详细介绍)。

我的环境是:

  • Windows 10 PRO 64位/ 8Gb RAM / CPU Intel 4核心
  • VMWare Player 12
  • 虚拟化操作系统Linux Mint 18.1 64位

  • 内核配置

    • 版本:4.10.0-24-generic
    • CONFIG_HIGH_RES_TIMERS = Y
    • CONFIG_POSIX_TIMERS = Y
    • CONFIG_NO_HZ_COMMON = Y
    • CONFIG_NO_HZ_IDLE = Y
    • CONFIG_NO_HZ = Y
    • CONFIG_HZ_250 = Y
    • CONFIG_HZ = 250

    • / SYS /装置/系统/ clocksource / clocksource0 / available_clocksource => tsc hpet acpi_pm

    • / SYS /装置/系统/ clocksource / clocksource0 / current_clocksource => TSC

为了做基准测试我写了一个linux内核模块,我在网址https://bitbucket.org/DareDevilDev/hr-timers-tester/上自由发布。在README文件中有自己编译和运行它的说明。

执行以下一系列循环:

  • 10 uS .. 90 uS,增量10 uS
  • 100 uS .. 900 uS,增量100 uS
  • 1 ms .. 9 ms,递增1 ms
  • 10 ms .. 90 ms,递增10 ms
  • 100 ms .. 900 ms,递增100 ms
  • 最后1 s

时间由" ktime_get"衡量。函数并存储在预先分配的数组中,以获得更快的性能,并避免hr计时器回调中的不必要的延迟。

收集数据后,模块会打印出样本数据表。

对于我的情景,相关数据是:

   10 uS =      41082 nS
   20 uS =      23955 nS
   30 uS =     478361 nS
   40 uS =      27341 nS
   50 uS =     806875 nS
   60 uS =     139721 nS
   70 uS =     963793 nS
   80 uS =      39475 nS
   90 uS =     175736 nS
  100 uS =    1096272 nS
  200 uS =      10099 nS
  300 uS =     967644 nS
  400 uS =     999006 nS
  500 uS =    1025254 nS
  600 uS =    1125488 nS
  700 uS =     982296 nS
  800 uS =    1011911 nS
  900 uS =     978652 nS
 1000 uS =    1985231 nS
 2000 uS =    1984367 nS
 3000 uS =    2068547 nS
 4000 uS =    5000319 nS
 5000 uS =    4144947 nS
 6000 uS =    6047991 nS <= First expected delay!
 7000 uS =    6835180 nS
 8000 uS =    8057504 nS
 9000 uS =    9218573 nS
10000 uS =   10435313 nS

......等等......

正如您在上面的内核日志转储中所看到的,6 ms是第一个预期的延迟样本。

我在C.H.I.P.上重复了相同的测试。嵌入式系统(https://getchip.com/pages/chip),基于ARM的板状Raspberry,运行频率为1 GHz,配备Ubuntu 14.04(内核4.4.13,HZ = 200)。

在这种情况下,我得到了更好的结果:

  30 =      44666 nS
  40 =      24125 nS
  50 =      49208 nS
  60 =      60208 nS
  70 =      70042 nS
  80 =      78334 nS
  90 =      89708 nS
 100 =     126083 nS
 200 =     184917 nS
 300 =     302917 nS <= First expected delay!
 400 =     395000 nS
 500 =     515333 nS
 600 =     591583 nS
 700 =     697458 nS
 800 =     800875 nS
 900 =     900125 nS
1000 =    1013375 nS

......等等......

在那个更便宜的电路板上,300美元以来取得了良好的效果。

你知道什么?是否有更好的方法可以通过独立于平台的方式从HR定时器获得更高的精度? HR定时器是精确定时的错误解决方案(当我们必须编写硬件驱动程序时必须使用)?

每个贡献都将非常感激。

谢谢!

1 个答案:

答案 0 :(得分:0)

问题解决了,这是虚拟化环境所涉及的一个问题。

在一台旧笔记本电脑(HP Single Core 1.9GHz)上,自60年代以来我的延迟时间很长,而在较新的笔记本电脑上(戴尔四核),我的延迟时间低于10美元!