我试图触发大量内核时间以查看正在使用的系统调用的java进程,并且惊讶地看到gettimeofday()
和clock_gettime()
占主导地位(我怀疑它&# 39; s由于记录),考虑到man vdso
状态,这很奇怪:
使用 strace (1)跟踪系统调用时,vDSO导出的符号(系统调用)不会出现在跟踪输出中。
为什么这些系统调用正在发生?有没有办法避免它们?
机器在EC2上运行Ubuntu 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
ldd ./testgtod
以确保vDSO处于活动状态:
linux-vdso.so.1 =&gt; (0x00007ffcee25d000) libc.so.6 =&gt; /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
答案 0 :(得分:4)
这个问题与在Xen上运行的VM有关,具体来说,Xen clocksource还不允许vDSO访问时钟:
ubuntu@machine:~% cat /sys/devices/system/clocksource/*/current_clocksource
xen
然后,我将clocksource更改为tsc
:
ubuntu@machine:~% sudo sh -c "echo tsc >/sys/devices/system/clocksource/clocksource0/current_clocksource"
注意:建议不要转移到生产机器上的 tsc
clocksource,因为它可能导致时钟向后漂移。
有关vDSO与clocksource之间交互的详细说明,请参阅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版本。亚马逊在re:Invent 2015(https://www.slideshare.net/AmazonWebServices/cmp402-amazon-ec2-instances-deep-dive)中推荐了tsc
clocksource。我还没有投入生产,但情况似乎并不像packagecloud那样糟糕。
补充阅读:
Why rdtsc
interacts poorly with VMs
Xen's 4.0 rdtsc changes
Linux kernel timekeeping documentation, discussing the pitfalls of the TSC