Измерение времени, затраченного функцией: clock_gettime

Я пытаюсь измерить, сколько времени занимает функция.

У меня небольшая проблема: хотя я стараюсь быть точным и использую числа с плавающей запятой, каждый раз, когда я печатаю свой код с помощью %lf, я получаю один из двух ответов: _2 _... или _3 _... Это заставляет меня задаться вопросом, а мой код правильный:

#define BILLION  1000000000L;

// Calculate time taken by a request
struct timespec requestStart, requestEnd;
clock_gettime(CLOCK_REALTIME, &requestStart);
function_call();
clock_gettime(CLOCK_REALTIME, &requestEnd);

// Calculate time it took
double accum = ( requestEnd.tv_sec - requestStart.tv_sec )
  + ( requestEnd.tv_nsec - requestStart.tv_nsec )
  / BILLION;
printf( "%lf\n", accum );

Большая часть этого кода была написана не мной. В этом примере страницы был код, иллюстрирующий использование clock_gettime:

Может ли кто-нибудь сообщить мне, что неверно, или почему я получаю только int значения?


person Jary    schedule 15.10.2010    source источник
comment
Нет, нет, нет: не называйте числа. Вместо этого используйте функцию, которую они обслуживают: #define CLOCK_PRECISION 1000000000L /* one billion */   -  person pmg    schedule 16.10.2010
comment
@pmg: Касательная к педантичности: я бы сказал, что такое имя, как CLOCK_PRECISION, было бы необходимо только в том случае, если бы единицы не были ясны из имени переменной. В приведенном выше случае из названия tv_nsec ясно, что мы находимся в наносекундах. Так что NANOSECONDS_PER_SECOND может быть подходящим, но на самом деле это не сильно отличается от простого BILLION.   -  person Oliver Charlesworth    schedule 16.10.2010
comment
На CLOCK_REALTIME влияют скачки системного времени. Рассмотрите возможность использования CLOCK_MONOTONIC_RAW - на него не влияют корректировки времени с adjtime() и скачки времени.   -  person Dmitry    schedule 07.06.2019


Ответы (4)


Деление целого числа на целое дает целое число. Попробуй это:

#define BILLION 1E9

И не ставьте точку с запятой в конце строки. #define - это директива препроцессора, а не инструкция, и включение точки с запятой привело к тому, что BILLION был определен как 1000000000L;, что сломалось бы, если бы вы попытались использовать его в большинстве контекстов. Вам повезло, потому что вы использовали его в самом конце выражения и вне скобок.

person Marcelo Cantos    schedule 15.10.2010
comment
Спасибо большое за вашу помощь. И спасибо, что сообщили мне о точке с запятой, я забыл об этом. Большое тебе спасибо! - person Jary; 16.10.2010
comment
Ради производительности .. #define ONE_OVER_BILLION 1E-9 и используйте multiply. - person linleno; 05.06.2016

( requestEnd.tv_nsec - requestStart.tv_nsec ) имеет целочисленный тип и всегда меньше BILLION, поэтому результатом деления одного на другое в целочисленной арифметике всегда будет 0. Вам нужно привести результат вычитания, например, к double перед делением.

person Oliver Charlesworth    schedule 15.10.2010

Обратите внимание, что (requestEnd.tv_nsec - requestStart.tv_nsec) может быть отрицательным, и в этом случае вам нужно вычесть 1 секунду из разницы tv_sec и добавить один МИЛЛИАРД к разнице tv_nsec.

person Wayfarer    schedule 02.12.2016
comment
Проголосовать против неверного ответа. В аналогичных расчетах что-то подобное может понадобиться, но не здесь. Если requestEnd.tv_nsec - requestStart.tv_nsec отрицательно, а BILLION является двойным 1E9, тогда (requestEnd.tv_nsec - requestStart.tv_nsec) / BILLION будет двойным между -1.0 и 0.0, и добавление этого числа к (requestEnd.tv_sec - requestStart.tv_sec) будет делать правильные вещи, потому что последнее неявно преобразуется в двойное. en.cppreference.com/w/c/language/conversion - person jcsahnwaldt Reinstate Monica; 27.11.2018

Я знаю, что вопрос был опубликован давно, но я до сих пор не вижу ответа, который предлагал бы вам преобразовать прошедшее время в наносекунды (или миллисекунды), а не в секунды, как в вашем примере кода.

Фрагмент кода примера, иллюстрирующий идею:

long long accum = ( requestEnd.tv_nsec - requestStart.tv_nsec )
 + ( requestEnd.tv_sec - requestStart.tv_sec ) * BILLION;

Таким образом вы можете избежать арифметики с плавающей запятой, которая может быть сложной для некоторых платформ ...

person AntonK    schedule 05.08.2017
comment
Должно быть / BILLION, а не * BILLION - person FractalSpace; 31.08.2020
comment
@FractalSpace, умножая, мы конвертируем секунды в наносекунды. - person AntonK; 02.09.2020
comment
Правильно. ваши единицы для accum находятся в нс, тогда как OP - в секундах - person FractalSpace; 02.09.2020