Как узнать время работы программы
Перейти к содержимому

Как узнать время работы программы

  • автор:

C/C++: как измерять процессорное время

image
КДПВ

От переводчика:
Большинство моих знакомых для измерения времени в разного вида бенчмарках в С++ используют chrono или, в особо запущенных случаях, ctime . Но для бенчмаркинга гораздо полезнее замерять процессорное время. Недавно я наткнулся на статью о кроссплатформенном замере процессорного времени и решил поделиться ею тут, возможно несколько увеличив качество местных бенчмарков.

P.S. Когда в статье написано «сегодня» или «сейчас», имеется ввиду «на момент выхода статьи», то есть, если я не ошибаюсь, март 2012. Ни я, ни автор не гарантируем, что это до сих пор так.
P.P.S. На момент публикации оригинал недоступен, но хранится в кэше Яндекса

Функции API, позволяющие получить процессорное время, использованное процессом, отличаются в разных операционных системах: Windows, Linux, OSX, BSD, Solaris, а также прочих UNIX-подобных ОС. Эта статья предоставляет кросс-платформенную функцию, получающую процессорное время процесса и объясняет, какие функции поддерживает каждая ОС.

Как получить процессорное время

Процессорное время увеличивается, когда процесс работает и потребляет циклы CPU. Во время операций ввода-вывода, блокировок потоков и других операций, которые приостанавливают работу процессора, процессорное время не увеличивается пока процесс снова не начнет использовать CPU.

Разные инструменты, такие как ps в POSIX, Activity Monitor в OSX и Task Manager в Windows показывают процессорное время, используемое процессами, но часто бывает полезным отслеживать его прямо из самого процесса. Это особенно полезно во время бенчмаркинга алгоритмов или маленькой части сложной программы. Несмотря на то, что все ОС предоставляют API для получения процессорного времени, в каждой из них есть свои тонкости.

Функция getCPUTime( ) , представленная ниже, работает на большинстве ОС (просто скопируйте код или скачайте файл getCPUTime.c). Там, где это нужно, слинкуйтесь с librt, чтобы получить POSIX-таймеры (например, AIX, BSD, Cygwin, HP-UX, Linux и Solaris, но не OSX). В противном случае, достаточно стандартных библиотек.

Далее мы подробно обсудим все функции, тонкости и причины, по которым в коде столько #ifdef ‘ов.

Использование

Чтобы замерить процессорное время алгоритма, вызовите getCPUTime( ) до и после запуска алгоритма, и выведите разницу. Не стоит предполагать, что значение, возвращенное при единичном вызове функции, несет какой-то смысл.

Обсуждение

Каждая ОС предоставляет один или несколько способов получить процессорное время. Однако некоторые способы точнее остальных.

OS clock clock_gettime GetProcessTimes getrusage times
AIX yes yes yes yes
BSD yes yes yes yes
HP-UX yes yes yes yes
Linux yes yes yes yes
OSX yes yes yes
Solaris yes yes yes yes
Windows yes

Каждый из этих способов подробно освещен ниже.

GetProcessTimes( )

На Windows и Cygwin (UNIX-подобная среда и интерфейс командной строки для Windows), функция GetProcessTimes( ) заполняет структуру FILETIME процессорным временем, использованным процессом, а функция FileTimeToSystemTime( ) конвертирует структуру FILETIME в структуру SYSTEMTIME, содержащую пригодное для использования значение времени.

Доступность GetProcessTimes( ): Cygwin, Windows XP и более поздние версии.

Получение процессорного времени:

clock_gettme( )

На большинстве POSIX-совместимых ОС, clock_gettime( ) (смотри мануалы к AIX, BSD, HP-UX, Linux и Solaris) предоставляет самое точное значение процессорного времени. Первый аргумент функции выбирает «clock id», а второй это структура timespec , заполняемая использованным процессорным временем в секундах и наносекундах. Для большинства ОС, программа должна быть слинкована с librt.

Однако, есть несколько тонкостей, затрудняющих использование этой функции в кросс-платформенном коде:

  • Функция является опциональной частью стандарта POSIX и доступна только если _POSIX_TIMERS определен в <unistd.h> значением больше 0. На сегодняшний день, AIX, BSD, HP-UX, Linux и Solaris поддерживают эту функцию, но OSX не поддерживает.
  • Структура timespec , заполняемая функцией clock_gettime( ) может хранить время в наносекундах, но точность часов отличается в разных ОС и на разных системах. Функция clock_getres( ) возвращает точность часов, если она вам нужна. Эта функция, опять-таки, является опциональной частью стандарта POSIX, доступной только если _POSIX_TIMERS больше нуля. На данный момент, AIX, BSD, HP-UX, Linux и Solaris предоставляют эту функцию, но в Solaris она не работает. определяет имена нескольких стандартных значений «clock id», включая CLOCK_PROCESS_CPUTIME_ID , чтобы получить процессорное время процесса. Тем не менее, сегодня BSD и HP-UX не имеют этого id, и взамен определяют собственный id CLOCK_VIRTUAL для процессорного времени. Чтобы запутать все ещё больше, Solaris определяет оба этих, но использует CLOCK_VIRTUAL для процессорного времени потока, а не процесса.
  • Вместо того, чтобы использовать одну из констант, объявленных выше, функция clock_getcpuclockid( ) возвращает таймер для выбранного процесса. Использование процесса 0 позволяет получить процессорное время текущего процесса. Однако, это ещё одна опциональная часть стандарта POSIX и доступна только если _POSIX_CPUTIME больше 0. На сегодняшний день, только AIX и Linux предоставляют эту функцию, но линуксовские include-файлы не определяют _POSIX_CPUTIME и функция возвращает ненадёжные и несовместимые с POSIX результаты.
  • Функция clock_gettime( ) может быть реализована с помощью регистра времени процессора. На многопроцессорных системах, у отдельных процессоров может быть несколько разное восприятие времени, из-за чего функция может возвращать неверные значения, если процесс передавался от процессора процессору. На Linux, и только на Linux, это может быть обнаружено, если clock_getcpuclockid( ) возвращает не-POSIX ошибку и устанавливает errno в ENOENT . Однако, как замечено выше, на Linux clock_getcpuclockid( ) ненадежен.

На практике из-за всех этих тонкостей, использование clock_gettime( ) требует много проверок с помощью #ifdef и возможность переключиться на другую функцию, если она не срабатывает.

Доступность clock_gettime( ): AIX, BSD, Cygwin, HP-UX, Linux и Solaris. Но clock id на BSD и HP-UX нестандартные.

Доступность clock_getres( ): AIX, BSD, Cygwin, HP-UX и Linux, но не работает Solaris.

Доступность clock_getcpuclockid( ): AIX и Cygwin, не недостоверна на Linux.

Получение процессорного времени:

getrusage( )

На всех UNIX-подобных ОС, функция getrusage( ) это самый надежный способ получить процессорное время, использованное текущим процессом. Функция заполняет структуру rusage временем в секундах и микросекундах. Поле ru_utime содержит время проведенное в user mode, а поле ru_stime — в system mode от имени процесса.

Внимание: Некоторые ОС, до широкого распространения поддержки 64-бит, определяли функцию getrusage( ) , возвращающую 32-битное значение, и функцию getrusage64( ) , возвращающую 64-битное значение. Сегодня, getrusage( ) возвращает 64-битное значение, а getrusage64( ) устарело.

Доступность getrusage( ): AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris.

Получение процессорного времени:

times( )

На всех UNIX-подобных ОС, устаревшая функция times( ) заполняет структуру tms с процессорным временем в тиках, а функция sysconf( ) возвращает количество тиков в секунду. Поле tms_utime содержит время, проведенное в user mode, а поле tms_stime — в system mode от имени процесса.

Внимание: Более старый аргумент функции sysconf( ) CLK_TCK устарел и может не поддерживаться в некоторых ОС. Если он доступен, функция sysconf( ) обычно не работает при его использовании. Используйте _SC_CLK_TCK вместо него.

Доступность times( ): AIX, BSD, Cygwin, HP-UX, Linux, OSX и Solaris.

Получение процессорного времени:

clock( )

На всех UNIX-подобных ОС, очень старая функция clock( ) возвращает процессорное время процесса в тиках, а макрос CLOCKS_PER_SEC количество тиков в секунду.

Заметка: Возвращенное процессорное время включает в себя время проведенное в user mode И в system mode от имени процесса.

Внимание: Хотя изначально CLOCKS_PER_SEC должен был возвращать значение, зависящее от процессора, стандарты C ISO C89 и C99, Single UNIX Specification и стандарт POSIX требуют, чтобы CLOCKS_PER_SEC имел фиксированное значение 1,000,000, что ограничивает точность функции микросекундами. Большинство ОС соответствует этим стандартам, но FreeBSD, Cygwin и старые версии OSX используют нестандартные значения.

Внимание: На AIX и Solaris, функция clock( ) включает процессорное время текущего процесса И и любого завершенного дочернего процесса для которого родитель выполнил одну из функций wait( ) , system( ) или pclose( ) .

Внимание: В Windows, функция clock( ) поддерживается, но возвращает не процессорное, а реальное время.

Доступность clock( ): AIX, BSD, Cygwin, HP-UX, Linux, OSX и Solaris.

Получение процессорного времени:

Другие подходы

Существуют и другие ОС-специфичные способы получить процессорное время. На Linux, Solarisи некоторых BSD, можно парсить /proc/[pid]/stat, чтобы получить статистику процесса. На OSX, приватная функция API proc_pidtaskinfo( ) в libproc возвращает информацию о процессе. Также существуют открытые библиотеки, такие как libproc, procps и Sigar.

На UNIX существует несколько утилит позволяющих отобразить процессорное время процесса, включая ps, top, mpstat и другие. Можно также использовать утилиту time, чтобы отобразить время, потраченное на команду.

На Windows, можно использовать диспетчер задач, чтобы мониторить использование CPU.

На OSX, можно использовать Activity Monitor, чтобы мониторить использование CPU. Утилита для профайлинга Instruments поставляемая в комплекте с Xcode может мониторить использование CPU, а также много других вещей.

Как замерить время выполнения

Зачастую требуется узнать, сколько времени выполняется тот или иной код. Иногда требуется замерить время выполнения метода или какой-то задачи. В данной статье мы расскажем вам принципы замера времени в Java и покажем лучшие практики для конкретных задач.

Замер времени с помощью currentTimeMills()

Это довольно простой способ измерить время. Метод System.currentTimeMillis() вернёт вам текущее время в миллисекундах. Его потребуется вызвать до выполнения нужной задачи и после, а затем вычислить разницу. В итоге мы узнаем время выполнения в миллисекундах:

При работе с данным методом следует учитывать его специфику: System.currentTimeMillis() показывает текущее время, основываясь на системных часах и может выдавать некорректный результат.

Замер времени с помощью nanoTime()

Ещё один метод для получения текущего времени это System.nanoTime(). Как следует из названия, этот метод возвращает время с точностью до нансекунд. Также работа этого метода не зависит от системных часов.

Он используется аналогично:

Для получения значения в миллисекундах результат можно разделить на 1000:

Важно: Хотя метод nanoTime() может возвращать время в наносекундах, он не гарантирует, что значения между его вызовами будут обновляться с точностью до наносекунд.

Но всё же это более приемлемый вариант, чем System.currentTimeMillis().

Замер времени с помощью Instant и Duration

В Java 8 добавили новый java.time API. В частности, ля измерения времени подойдут два новых класса – Instant и Duration. Оба эти класса иммутабельны.

Instant обозначает момент времени с начала эпохи Unix (1970-01-01T00:00:00Z). Для создания момента мы используем метод Instant.now(). После того, как мы создали два момент, вычислим разницу в миллисекундах:

Рекомендуется использовать именно этот подход в Java 8 и выше.

Замер времени выполнения с помощью StopWatch

StopWatch – это класс из библиотеки Apache Commons Lang. Он работает как секундомер. Для его использования сначала требуется подключить библиотеку к проекту:

Теперь создадим экземпляр StopWatch. Затем начнём отсчёт с помощью метода start() и окончим отсчёт с помощью метода stop():

StopWatch удобно использовать тогда, когда в проекте уже подключена данная библиотека.

Исходный код

Заключение

В данной статье мы разобрали простые методы замера времени выполнения в Java. Для простых замеров можно использовать все вышеперечисленные методы, кроме currentTimeMillis (из-за того, что он зависит от системных часов).

calculating execution time in c++

I have written a c++ program , I want to know how to calculate the time taken for execution so I won’t exceed the time limit.

this is my program and i want it to be within time limit 3 sec !! how to do it ? yeah sorry i meant execution time !!

9 Answers 9

If you have cygwin installed, from it’s bash shell, run your executable, say MyProgram , using the time utility, like so:

This will report how long the execution of your program took — the output would look something like the following:

You could also manually modify your C program to instrument it using the clock() library function, like so:

With C++11 for measuring the execution time of a piece of code, we can use the now() function:

If you want to print the time difference between start and end in the above code, you could use:

If you prefer to use nanoseconds, you will use:

The value of the diff variable can be also truncated to an integer value, for example, if you want the result expressed as:

For more info click here

OVERVIEW

I have written a simple semantic hack for this using @AshutoshMehra response. You code looks really readable this way!

MACRO

USAGE

OUTPUT

Mathew Kurian's user avatar

Note: the question was originally about compilation time, but later it turned out that the OP really meant execution time. But maybe this answer will still be useful for someone.

For Visual Studio: go to Tools / Options / Projects and Solutions / VC++ Project Settings and set Build Timing option to ‘ yes ‘. After that the time of every build will be displayed in the Output window.

Найдите время выполнения программы на C

В этом посте будет обсуждаться, как найти время выполнения программы C в средах Windows и Linux.

Существует четыре широко используемых метода определения времени выполнения программы на C:

1. Использование clock() функция

Мы можем использовать clock() функция, предоставляемая <time.h> заголовочный файл для расчета времени ЦП, потребляемого задачей в приложении C. Он возвращает clock_t type, в котором хранится общее количество тактов часов.

Чтобы вычислить общее количество прошедших секунд, нам нужно разделить общее количество прошедших тактов часов на CLOCKS_PER_SEC макрос (также присутствует в <time.h> ) как показано ниже:

Выход (может варьироваться):

The elapsed time is 0.000014 seconds

Обратите внимание, что clock() Функция не возвращает фактическое количество прошедшего времени, а возвращает количество времени, которое потребовалось базовой операционной системе для запуска процесса. Другими словами, фактическое время настенных часов может быть намного больше.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *