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

148

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

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

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

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

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

Мануэль Сельва
источник

Ответы:

198

Проблема заключается в том, что в 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()является опцией для синхронизации с очень высоким разрешением (нс) в OS X. В моей системе это действительно дает разрешение нс. В принципе, эти часы оборачиваются, однако они хранят 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поле struct.

Дуглас Б. Штапель
источник
Mac OS X не имеет clock_gettime, поэтому использование gettimeofday()немного более универсальным, чемclock_gettime()
bobobobo
1
Вы не упомянули times()(с буквой s), которая существует в POSIX с момента выпуска 1. Относительно GNU / Linux: Согласно man-странице clock (3), clock()из glibc 2.17 и более ранних версий был реализован поверх него, но для улучшения точность, теперь она реализована поверх clock_gettime(CLOCK_PROCESS_CPUTIME_ID,...), что также указано в POSIX, но не является обязательным.
vinc17
2
@starflyer Точность часов частично ограничена количеством времени, которое требуется для опроса часов. Это связано с тем, что если я вызываю часы, и для их возврата требуется 1 мкс, то время, в течение которого отчеты о часах будут «выключены», на 1 мкс с точки зрения вызывающего абонента. Это означает, что высокоточные часы также должны иметь низкую задержку. Таким образом, обычно у вас не будет компромисса, о котором вы говорите: самые дешевые часы также будут самыми точными.
Дуглас Б. Стейпл
3
Также большинство часов не заботятся о переходе на летнее время / часовые пояса, даже если они считаются настенными часами . Оба timeи gettimeofdayвозвращают, по крайней мере, в настоящее время, секунды с начала эпохи (или unix-timestamps). Это не зависит от часовых поясов / летнего времени. Еще одна история
Зулан,
2
Для пользователей Android использование CLOCK_MONOTONIC может быть проблематичным, поскольку приложение может быть приостановлено вместе с часами. Для этого Android добавил таймер ANDROID_ALARM_ELAPSED_REALTIME, который доступен через ioctl. некоторую информацию об этой и другой информации о приостановке можно найти здесь
Итай Бьянко
17

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_REALTIMEPOSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html , и man clock_gettimeговорит, что эта мера может иметь разрывы, если вы измените некоторые настройки системного времени во время работы вашей программы.

С ++ 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_REALTIMEvs CLOCK_MONOTONIC: разница между CLOCK_REALTIME и CLOCK_MONOTONIC?

Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
1
Отличный ответ, который демистифицирует типичные реализации. Это то, что людям действительно нужно знать.
Celess