gettimeofday() не использует vDSO?

Я связал Java-процесс, который запускал много времени в ядре, чтобы увидеть, какие системные вызовы использовались, и был удивлен, увидев, что gettimeofday() а также clock_gettime() доминирует (я подозреваю, что это из-за регистрации), что странно, учитывая, что man vdso состояния:

При трассировке системных вызовов с помощью strace(1) символы (системные вызовы), экспортируемые vDSO, не будут отображаться в выходных данных трассировки.

Почему эти системные вызовы происходят? Есть ли способ их избежать?

Машина работает под управлением Ubuntu 16.04.1 на EC2.

Чтобы было проще, я создал минимальную тестовую программу на 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. Убедитесь, что двоичный файл является 64-битным эльфом, использующим file

  2. 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)

  3. getauxval(AT_SYSINFO_EHDR) != NULL

  4. Заменены gettimeofday(&tv, NULL) звонки с syscall(SYS_gettimeofday, &tv, NULL), увеличил количество звонков до 10 миллионов, побежал под time - поведение во время выполнения было одинаковым в обоих случаях: ./testgtod 0.16s user 0.83s system 99% cpu 0.998 total,

1 ответ

Решение

Проблема связана с тем, что это виртуальная машина, работающая на Xen, в частности, источник синхронизации 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 Clocksource на производственных машинах, так как это может вызвать обратный дрейф для часов.

См. https://blog.packagecloud.io/eng/2017/03/08/system-calls-are-much-slower-on-ec2/ для подробного описания взаимодействия между vDSO и источником синхронизации.

ПРИМЕЧАНИЕ 2: кажется tsc поддержка в Xen улучшена с версией 4.0 и с улучшенной поддержкой ЦП на платформах Sandy Bridge+. Современные машины EC2 должны быть в порядке с tsc, Проверьте версию Xen, используя dmesg | grep "Xen version", Amazon рекомендовал tsc Clocksource уже в re: Invent 2015 ( https://www.slideshare.net/AmazonWebServices/cmp402-amazon-ec2-instances-deep-dive). Я еще не приступил к работе с этим, но ситуация не так плоха, как подразумевает packagecloud.

Дополнительное чтение:
Зачем rdtsc плохо взаимодействует с виртуальными машинами
Изменения Xen 4.0 rdtsc
Документация о времени работы ядра Linux, обсуждение подводных камней TSC

Другие вопросы по тегам