gettimeofday() 不使用 vDSO?
gettimeofday() not using vDSO?
我跟踪了一个触发大量内核时间的 java 进程以查看正在使用的系统调用,并且惊讶地发现 gettimeofday()
和 clock_gettime()
占主导地位(我怀疑这是由于日志记录),这是 st运行ge 考虑到 man vdso
状态:
当使用 strace(1) 跟踪系统调用时,vDSO 导出的符号(系统调用)将不会出现在跟踪输出中。
为什么会发生这些系统调用?有没有办法避免它们?
机器是 运行 Ubuntu EC2 上的 16.04.1。
为了让事情更简单,我用 C (testgtod.c
) 创建了一个最小的测试程序:
#include <stdlib.h>
#include <sys/time.h>
void main(void)
{
struct timeval tv;
for(int i = 0; i < 1000; i++) {
/* glibc wrapped, shouldn't actually syscall */
gettimeofday(&tv, NULL);
}
}
然后我编译并运行 strace 下的程序:gcc testgtod.c -o testgtod && sudo strace ./testgtod
输出包括对 gettimeofday() 的一千次调用,尽管我的期望如此。
我测试过的东西以确保我没有看到东西:
使用 file
确保二进制文件是 64 位 elf
ldd ./testgtod
确保 vDSO 处于活动状态:
linux-vdso.so.1 => (0x00007ffcee25d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6f6e161000)
/lib64/ld-linux-x86-64.so.2 (0x0000559ed71f3000)
getauxval(AT_SYSINFO_EHDR) != NULL
将 gettimeofday(&tv, NULL)
调用替换为 syscall(SYS_gettimeofday, &tv, NULL)
,调用次数增加到 1000 万,time
下的 运行 - 运行时行为与两种情况:./testgtod 0.16s user 0.83s system 99% cpu 0.998 total
.
问题与这是 Xen 上的 VM 运行 有关,具体来说,Xen 时钟源还不允许 vDSO 访问时钟:
ubuntu@machine:~% cat /sys/devices/system/clocksource/*/current_clocksource
xen
然后,我将时钟源更改为 tsc
:
ubuntu@machine:~% sudo sh -c "echo tsc >/sys/devices/system/clocksource/clocksource0/current_clocksource"
注意: 不建议在生产机器上移动到 tsc
时钟源,因为它可能导致时钟向后漂移。
有关 vDSO 和时钟源之间交互的详细说明,请参阅 https://blog.packagecloud.io/eng/2017/03/08/system-calls-are-much-slower-on-ec2/。
注意 2:Xen 中的 tsc
支持似乎在版本 4.0 中得到了改进,并且在 Sandy Bridge+ 平台中的 CPU 支持得到了改进。现代 EC2 机器应该可以使用 tsc
。使用 dmesg | grep "Xen version"
检查 Xen 版本。 Amazon 已在 re:Invent 2015 (https://www.slideshare.net/AmazonWebServices/cmp402-amazon-ec2-instances-deep-dive) 中推荐了 tsc
时钟源。我还没有 运行 生产这个,但情况似乎并不像 packagecloud 暗示的那么糟糕。
补充阅读:
Why rdtsc
interacts poorly with VMs
Xen's 4.0 rdtsc changes
Linux kernel timekeeping documentation, discussing the pitfalls of the TSC
我跟踪了一个触发大量内核时间的 java 进程以查看正在使用的系统调用,并且惊讶地发现 gettimeofday()
和 clock_gettime()
占主导地位(我怀疑这是由于日志记录),这是 st运行ge 考虑到 man vdso
状态:
当使用 strace(1) 跟踪系统调用时,vDSO 导出的符号(系统调用)将不会出现在跟踪输出中。
为什么会发生这些系统调用?有没有办法避免它们?
机器是 运行 Ubuntu EC2 上的 16.04.1。
为了让事情更简单,我用 C (testgtod.c
) 创建了一个最小的测试程序:
#include <stdlib.h>
#include <sys/time.h>
void main(void)
{
struct timeval tv;
for(int i = 0; i < 1000; i++) {
/* glibc wrapped, shouldn't actually syscall */
gettimeofday(&tv, NULL);
}
}
然后我编译并运行 strace 下的程序:gcc testgtod.c -o testgtod && sudo strace ./testgtod
输出包括对 gettimeofday() 的一千次调用,尽管我的期望如此。
我测试过的东西以确保我没有看到东西:
使用
file
确保二进制文件是 64 位 elf
ldd ./testgtod
确保 vDSO 处于活动状态:linux-vdso.so.1 => (0x00007ffcee25d000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6f6e161000) /lib64/ld-linux-x86-64.so.2 (0x0000559ed71f3000)
getauxval(AT_SYSINFO_EHDR) != NULL
将
gettimeofday(&tv, NULL)
调用替换为syscall(SYS_gettimeofday, &tv, NULL)
,调用次数增加到 1000 万,time
下的 运行 - 运行时行为与两种情况:./testgtod 0.16s user 0.83s system 99% cpu 0.998 total
.
问题与这是 Xen 上的 VM 运行 有关,具体来说,Xen 时钟源还不允许 vDSO 访问时钟:
ubuntu@machine:~% cat /sys/devices/system/clocksource/*/current_clocksource
xen
然后,我将时钟源更改为 tsc
:
ubuntu@machine:~% sudo sh -c "echo tsc >/sys/devices/system/clocksource/clocksource0/current_clocksource"
注意: 不建议在生产机器上移动到 tsc
时钟源,因为它可能导致时钟向后漂移。
有关 vDSO 和时钟源之间交互的详细说明,请参阅 https://blog.packagecloud.io/eng/2017/03/08/system-calls-are-much-slower-on-ec2/。
注意 2:Xen 中的 tsc
支持似乎在版本 4.0 中得到了改进,并且在 Sandy Bridge+ 平台中的 CPU 支持得到了改进。现代 EC2 机器应该可以使用 tsc
。使用 dmesg | grep "Xen version"
检查 Xen 版本。 Amazon 已在 re:Invent 2015 (https://www.slideshare.net/AmazonWebServices/cmp402-amazon-ec2-instances-deep-dive) 中推荐了 tsc
时钟源。我还没有 运行 生产这个,但情况似乎并不像 packagecloud 暗示的那么糟糕。
补充阅读:
Why rdtsc
interacts poorly with VMs
Xen's 4.0 rdtsc changes
Linux kernel timekeeping documentation, discussing the pitfalls of the TSC