gettimeofday()不使用vDSO?

时间:2017-03-06 09:53:39

标签: amazon-ec2 linux-kernel vdso

我试图触发大量内核时间以查看正在使用的系统调用的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()的一千次调用。

我测试的东西,以确保我没有看到的东西:

  1. 使用file

  2. 确保二进制文件是64位精灵
  3. 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)

  4. getauxval(AT_SYSINFO_EHDR) != NULL

  5. gettimeofday(&tv, NULL)次呼叫替换为syscall(SYS_gettimeofday, &tv, NULL),呼叫次数增加到1000万次,在time下运行 - 两种情况下的运行时行为相同:./testgtod 0.16s user 0.83s system 99% cpu 0.998 total

1 个答案:

答案 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