it-swarm.com.ru

Измерить время в Linux - время против часов против getrusage против clock_gettime против gettimeofday против timespec_get?

Среди функций синхронизации: time, clockgetrusage, clock_gettime, gettimeofday и timespec_get, я хочу ясно понять, как они реализованы и каковы их возвращаемые значения, чтобы знать, в какой ситуации я должен их использовать.

Сначала нам нужно классифицировать функции, возвращающие значения настенных часов, сравнивать с функциями, возвращающими значения процессов или потоков. gettimeofday возвращает значение настенных часов, clock_gettime возвращает значение настенных часов или значения процесса или потоков в зависимости от переданного ему параметра Clock. getrusage и clock возвращают значения процесса.

Тогда второй вопрос касается реализации этих функций и, как следствие, их точности. Какой аппаратный или программный механизм использует эти функции.

Кажется, что getrusage использует только тик ядра (обычно длиной 1 мс) и, как следствие, не может быть более точным, чем мс. Это правильно? Тогда функция getimeofday, похоже, использует самое точное из доступных аппаратных средств. Как следствие, его точность обычно составляет микросекунду (не может быть больше из-за API) на новейшем оборудовании. А как насчет clock, справочная страница говорит о "приближении", что это значит? Как насчет clock_gettime, API находится в наносекунде, означает ли это, что он может быть настолько точным, если базовое оборудование это позволяет? Как насчет монотонности?

Есть ли другие функции?

136
Manuel Selva

Проблема заключается в том, что в C и C++ доступно несколько различных временных функций, и некоторые из них различаются по поведению в разных реализациях. Есть также много полуответов, плавающих вокруг. Составление списка функций часов вместе с их свойствами ответило бы на вопрос правильно. Для начала давайте спросим, ​​какие релевантные свойства мы ищем. Глядя на ваш пост, я предлагаю:

  • Какое время измеряется часами? (реальный, пользовательский, системный или, надеюсь, нет, настенные часы?)
  • Какова точность часов? (с, мс, мкс или быстрее?)
  • Через сколько часов часы вращаются? Или есть какой-то механизм, чтобы этого избежать?
  • Являются ли часы монотонными или будут меняться при изменении системного времени (через NTP, часовой пояс, переход на летнее время, пользователем и т.д.)?
  • Как вышеописанное зависит от реализации?
  • Является ли конкретная функция устаревшей, нестандартной и т.д.?

Прежде чем приступить к списку, я хотел бы отметить, что время настенных часов редко является подходящим временем для использования, в то время как оно меняется с изменениями часового пояса, переходами на летнее время или если настенные часы синхронизируются по NTP. Ничто из этого не подходит, если вы используете время для планирования событий или оценки производительности. Это действительно хорошо для того, что говорит название, часы на стене (или на рабочем столе).

Вот что я нашел для часов в Linux и OS X:

  • time() возвращает время настенных часов из ОС с точностью до секунд.
  • clock() , кажется, возвращает сумму пользовательского и системного времени. Это присутствует в C89 и позже. Когда-то это должно было быть время процессора в циклах, но современные стандарты такие как POSIX требуют, чтобы CLOCKS_PER_SEC было 1000000, что дает максимально возможную точность в 1 мкс. Точность в моей системе действительно составляет 1 мкс. Эти часы вращаются, как только достигают максимума (это обычно происходит после ~ 2 ^ 32 тактов, что не очень долго для тактовой частоты 1 МГц). man clock говорит, что начиная с glibc 2.18 он реализован с clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) в Linux.
  • clock_gettime(CLOCK_MONOTONIC, ...) обеспечивает разрешение наносекунды, является монотонным. Я считаю, что "секунды" и "наносекунды" хранятся отдельно, каждый в 32-битных счетчиках. Таким образом, любое изменение будет происходить после многих десятков лет безотказной работы. Это похоже на очень хорошие часы, но, к сожалению, они еще не доступны в OS X. POSIX 7 описывает CLOCK_MONOTONIC как необязательное расширение .
  • getrusage() оказался лучшим выбором для моей ситуации. Он сообщает о времени пользователя и системы отдельно и не переносит их. Точность в моей системе составляет 1 мкс, но я также тестировал ее в системе Linux (Red Hat 4.1.2-48 с GCC 4.1.2), и там точность была всего 1 мс.
  • gettimeofday() возвращает время настенных часов с (номинально) мкс точностью. В моей системе эти часы имеют точность с точностью до мкс, но это не гарантируется, потому что "разрешение системных часов зависит от аппаратного обеспечения" . POSIX.1-2008 говорит, что . "Приложения должны использовать функцию clock_gettime() вместо устаревшей функции gettimeofday()", поэтому вам следует держаться подальше от нее. Linux x86 и реализует его как системный вызов .
  • mach_absolute_time() - это опция для синхронизации с очень высоким разрешением (ns) в OS X. В моей системе это действительно дает разрешение ns. В принципе, эти часы оборачиваются, однако они хранят ns, используя 64-разрядное целое число без знака, поэтому на практике оборачивание не должно быть проблемой. Переносимость сомнительна.
  • я написал гибридную функцию на основе этот фрагмент , который использует clock_gettime при компиляции в Linux или таймер Маха при компиляции в OS X, чтобы получить точность ns для обоих Linux и OS X.

Все вышеперечисленное существует как в Linux, так и в OS X, если не указано иное. "Моя система", описанная выше, - это Apple под управлением OS X 10.8.3 с GCC 4.7.2 от MacPorts.

Наконец, вот список ссылок, которые я нашел полезными в дополнение к ссылкам выше:


Обновление : для OS X clock_gettime был реализован с 10.12 (Sierra). Кроме того, платформы на основе POSIX и BSD (например, OS X) совместно используют поле структуры rusage.ru_utime.

181
Douglas B. Staple

C11 timespec_get

Пример использования по адресу: https://stackoverflow.com/a/36095407/895245

Максимально возможная возвращаемая точность составляет наносекунды, но фактическая точность определяется реализацией и может быть меньше.

Он возвращает время стены, а не использование процессора.

glibc 2.21 реализует его в sysdeps/posix/timespec_get.c и перенаправляет непосредственно в:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettime и CLOCK_REALTIME являются POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html , а man clock_gettime говорит, что эта мера может иметь разрывы, если вы измените некоторые настройки системного времени, пока вы Программа работает.

C++ 11 хронограф

Поскольку мы занимаемся этим, давайте рассмотрим их также: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C++ stdlib находится внутри источника GCC):

  • high_resolution_clock это псевдоним для system_clock
  • system_clock переадресация к первому доступному из следующего:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock переадресация к первому доступному из следующего:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

На вопрос: Разница между std :: system_clock и std :: stable_clock?

CLOCK_REALTIME против CLOCK_MONOTONIC: Разница между CLOCK_REALTIME и CLOCK_MONOTONIC?