HR 计时器精度研究案例
A HR timers precision study case
有了这个话题,我会更好地讨论 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。
HR 计时器承诺在 jiffies 分辨率下进行,但不幸的是,在我的系统上,我没有得到低于 6 毫秒的延迟的预期结果(我将在稍后显示更多详细信息)。
我的环境是:
- Windows 10 PRO 64 位/8Gb 内存/CPU Intel 4 核
- VMWare 播放器 12
虚拟化 OS 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/devices/system/clocksource/clocksource0/available_clocksource
=> tsc hpet acpi_pm
/sys/devices/system/clocksource/clocksource0/current_clocksource
=> tsc
为了做一个基准测试,我写了一个 linux 内核模块,我在 url https://bitbucket.org/DareDevilDev/hr-timers-tester/ 上自由发布了它。在 README 文件中有自己编译和 运行 的说明。
它执行如下一系列循环:
- 10 uS .. 90 uS,增加 10 uS
- 100 uS .. 900 uS,增加 100 uS
- 1 毫秒 .. 9 毫秒,增加 1 毫秒
- 10 毫秒 .. 90 毫秒,增加 10 毫秒
- 100 毫秒 .. 900 毫秒,增加 100 毫秒
- 最后1秒
计时由 "ktime_get" 函数测量并存储在预先分配的数组中,以提高性能并避免 hr 计时器回调内不必要的延迟。
采集数据后,模块打印出采样数据table。
对于我的场景相关数据是:
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 毫秒是第一个预期延迟样本。
我在 C.H.I.P 上重复了同样的测试。嵌入式系统 ( https://getchip.com/pages/chip ),一个基于 ARM 的板子 Raspberry,运行ning 在 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 定时器是精确计时的错误解决方案(当我们必须编写硬件驱动程序时是强制性的)?
我们将不胜感激。
谢谢!
问题已解决,是虚拟化环境的问题
在旧笔记本电脑(HP 单核 1.9GHz)上,我的延迟从 60 uS 开始很好,而在较新的笔记本电脑(戴尔四核)上,我的延迟低于 10 uS!
有了这个话题,我会更好地讨论 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。
HR 计时器承诺在 jiffies 分辨率下进行,但不幸的是,在我的系统上,我没有得到低于 6 毫秒的延迟的预期结果(我将在稍后显示更多详细信息)。
我的环境是:
- Windows 10 PRO 64 位/8Gb 内存/CPU Intel 4 核
- VMWare 播放器 12
虚拟化 OS 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/devices/system/clocksource/clocksource0/available_clocksource => tsc hpet acpi_pm
/sys/devices/system/clocksource/clocksource0/current_clocksource => tsc
为了做一个基准测试,我写了一个 linux 内核模块,我在 url https://bitbucket.org/DareDevilDev/hr-timers-tester/ 上自由发布了它。在 README 文件中有自己编译和 运行 的说明。
它执行如下一系列循环:
- 10 uS .. 90 uS,增加 10 uS
- 100 uS .. 900 uS,增加 100 uS
- 1 毫秒 .. 9 毫秒,增加 1 毫秒
- 10 毫秒 .. 90 毫秒,增加 10 毫秒
- 100 毫秒 .. 900 毫秒,增加 100 毫秒
- 最后1秒
计时由 "ktime_get" 函数测量并存储在预先分配的数组中,以提高性能并避免 hr 计时器回调内不必要的延迟。
采集数据后,模块打印出采样数据table。
对于我的场景相关数据是:
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 毫秒是第一个预期延迟样本。
我在 C.H.I.P 上重复了同样的测试。嵌入式系统 ( https://getchip.com/pages/chip ),一个基于 ARM 的板子 Raspberry,运行ning 在 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 定时器是精确计时的错误解决方案(当我们必须编写硬件驱动程序时是强制性的)?
我们将不胜感激。
谢谢!
问题已解决,是虚拟化环境的问题
在旧笔记本电脑(HP 单核 1.9GHz)上,我的延迟从 60 uS 开始很好,而在较新的笔记本电脑(戴尔四核)上,我的延迟低于 10 uS!