Легко измерить прошедшее время

297

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

Что я не понимаю, так это то, почему значения в до и после одинаковы? Я понимаю, что это не лучший способ для профилирования моей программы, я просто хочу посмотреть, как долго что-то займет.

printf("**MyProgram::before time= %ld\n", time(NULL));

doSomthing();
doSomthingLong();

printf("**MyProgram::after time= %ld\n", time(NULL));

Я пытался:

struct timeval diff, startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

timersub(&endTV, &startTV, &diff);

printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);

Как мне прочитать результат **time taken = 0 26339? Означает ли это, что 26,339 наносекунд = 26,3 мсек?

А что **time taken = 4 45025, это означает 4 секунды и 25 мс?

hap497
источник
10
Я не понимаю вопроса. Конечно значения разные. Время прошло между ними, поэтому time()возвращает другое значение.
Томас
1
Что вы имеете в виду «я не понимаю, почему значения в до и после разные»? Вы получаете текущее время (в секундах с 1 января 1970 года), используя time(NULL)... во второй раз, когда вы звоните, оно будет через N секунд после первого и, следовательно, ... другим (если вы не делаете не займет и секунды, чтобы завершить ... в этом случае это будет так же, как первый).
Брайан Роуч
1
Можете ли вы сказать нам, что он печатает, и сколько времени это займет, если вы рассчитываете его с помощью секундомера или настенных часов (или календаря)?
Мэтт Кертис
4
Извините, я имею в виду, что оба значения одинаковы. Я неправильно набрал свой вопрос.
hap497
2
Смотрите эту ветку: stackoverflow.com/questions/275004/…
умолчанию

Ответы:

336
//***C++11 Style:***
#include <chrono>

std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;
user3762106
источник
10
да, это должен быть ответ
Ференц Дайка
23
Для запуска этого нужно добавить #include <chrono>директиву и я хотел бы изменить время представления отчетности , как: std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;(и не забыть C ++ 11 флага при компиляции: -std=c++11)
Антонелло
1
Кстати, это измеряет время процессора, а не время настенных часов. Правильно?
Никос
4
@ RestlessC0bra Согласно документации по cppreference: «Эти часы не связаны со временем настенных часов (например, это может быть время с момента последней перезагрузки) и наиболее подходят для измерения интервалов».
цис
1
Какой это тип данных? Std :: chrono :: duration_cast <std :: chrono :: microseconds> (конец - начало) .count ()
sqp_125
272
#include <ctime>

void f() {
  using namespace std;
  clock_t begin = clock();

  code_to_time();

  clock_t end = clock();
  double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}

time()Функция является точной только в течение одной секунды, но есть CLOCKS_PER_SEC«часы» в течение одной секунды. Это простое, портативное измерение, даже если оно чрезмерно упрощено.


источник
129
Имейте в виду, что clock()измеряет процессорное время, а не фактическое истекшее время (которое может быть намного больше).
Jlstrecker
12
При программировании параллельного кода для кластеров этот метод не отражает реального времени ...
Николас Гамильтон
3
Это кажется самым простым из способов. Не хотите ли обновить комментарий или написать адрес @jlstrecker?
Лора Атткинс
5
Вышеуказанное решение не является хорошим решением по многим причинам. Это правильный ответ - stackoverflow.com/questions/2962785/…
Xofo
1
Я попробовал это решение, и, как показывают комментарии, мой таймер работал намного быстрее, чем в реальном времени.
RTbecard
267

Вы можете абстрагировать механизм измерения времени и измерять время выполнения каждого вызываемого объекта с минимальным дополнительным кодом , просто вызывая его через структуру таймера. Кроме того, во время компиляции вы можете параметризовать тип синхронизации (миллисекунды, наносекунды и т. Д.).

Благодаря обзору Loki Astari и предложению использовать вариадические шаблоны. Вот почему перенаправленный вызов функции.

#include <iostream>
#include <chrono>

template<typename TimeT = std::chrono::milliseconds>
struct measure
{
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F&& func, Args&&... args)
    {
        auto start = std::chrono::steady_clock::now();
        std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT> 
                            (std::chrono::steady_clock::now() - start);
        return duration.count();
    }
};

int main() {
    std::cout << measure<>::execution(functor(dummy)) << std::endl;
}

Demo

Согласно комментарию Говарда Хиннанта , лучше не выходить из системы хронографа, пока мы не должны. Таким образом, вышеприведенный класс может дать пользователю возможность countвручную вызывать , предоставляя дополнительный статический метод (показано в C ++ 14).

template<typename F, typename ...Args>
static auto duration(F&& func, Args&&... args)
{
    auto start = std::chrono::steady_clock::now();
    std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
    return std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now()-start);
} 

// call .count() manually later when needed (eg IO)
auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2.0;

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

«хотите обработать несколько периодов до ввода-вывода (например, в среднем)»


Полный код можно найти здесь . Моя попытка создать инструмент для тестирования производительности на основе хронографа описана здесь .


Если std::invokeдоступны C ++ 17 , вызов вызываемого объекта executionможет быть выполнен следующим образом:

invoke(forward<decltype(func)>(func), forward<Args>(args)...);

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

Никос Атанасиу
источник
2
Ницца; У меня есть что-то похожее в моем коде, но я использую другой интерфейс к классу: у меня есть class ( code_timer), который принимает время начала ( std::chrono::system_clock::now();) в конструкторе, метод, code_timer::ellapsedкоторый измеряет разницу между новым now()вызовом и тем, что в конструкторе и code_timer::resetметод, который сбрасывает время начала до нового now()результата. Чтобы измерить выполнение функтора в моем коде, я использую свободную функцию вне класса. Это позволяет измерять время от построения объекта до завершения асинхронного вызова.
utnapistim
7
<nitpick>: не выходите из chronoсистемы, пока вам не придется (избегайте использования .count()). Пусть клиент звонит, .count()когда вынужден (скажем, для ввода / вывода, что действительно неудачно). Клиент может захотеть постобработать несколько периодов до ввода / вывода (например, в среднем), и это лучше всего сделать в chronoсистеме.
Говард Хиннант
1
@ user3241228 1. VS2013 не поддерживает типы с автоматическим возвратом (только конечные типы с возвратом - функция C ++ 14 еще не доступна). 2. Я полагаю, что это причина, но я спросил aq просто чтобы быть уверенным
Никос Атанасиу
2
Почему нет std::forward<F>(func)?
oliora
3
@oliora Это то же самое. Я предпочитаю, std::forward<decltype(func)>(func)потому что он может применяться к аргументам универсального lambdas ( auto&& func), где Fнет синтаксического там, и его легко абстрагировать в служебном макросе, #define fw(arg) std::forward<decltype(arg)>(arg)который я делаю в моей библиотеке тестов (так что это синтаксический остаток, над которым я не особо разбираюсь) ответ)
Никос Атанасиу
56

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

#include <time.h>
#include <stdio.h>

time_t start,end;
time (&start);
.
.
.
<your code>
.
.
.
time (&end);
double dif = difftime (end,start);
printf ("Elasped time is %.2lf seconds.", dif );
Akanthan
источник
4
Это всегда дает мне целые секунды. Это должно случиться?
нитрат натрия
10
время всегда будет возвращать только секунды, поэтому его нельзя использовать для измерений менее секунды.
DeepDeadpool
31

Только для Windows: (тег Linux был добавлен после того, как я опубликовал этот ответ)

Вы можете использовать GetTickCount (), чтобы получить количество миллисекунд, прошедших с момента запуска системы.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();
RvdK
источник
7
Я использую это на Linux. Поэтому я не могу использовать функцию GetTickCount ().
hap497
1
уже не
бери в
Он работает и дает реальное время, а не процессорное время. Я проверил это, поместив SleepEx(5000,0)вместо // Выполнение трудоемкой операции и разность afterи beforeсоставила почти 5 секунд.
Ruchir
14

time(NULL)возвращает количество секунд, прошедших с 01.01.1970 в 00:00 ( эпоха ). Таким образом, разница между двумя значениями - это количество секунд, затраченное на обработку.

int t0 = time(NULL);
doSomthing();
doSomthingLong();
int t1 = time(NULL);

printf ("time = %d secs\n", t1 - t0);

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

philant
источник
13

функция времени (NULL) возвращает количество секунд, прошедших с 01.01.1970 в 00:00. И поскольку эта функция вызывается в разное время в вашей программе, она всегда будет разной. Время в C ++

vodkhang
источник
Я не знаю, почему кто-то проголосовал, но ваш ответ не совсем правильный. Для начала он не возвращает дату и не всегда будет другим.
Matt Joiner
12
struct profiler
{
    std::string name;
    std::chrono::high_resolution_clock::time_point p;
    profiler(std::string const &n) :
        name(n), p(std::chrono::high_resolution_clock::now()) { }
    ~profiler()
    {
        using dura = std::chrono::duration<double>;
        auto d = std::chrono::high_resolution_clock::now() - p;
        std::cout << name << ": "
            << std::chrono::duration_cast<dura>(d).count()
            << std::endl;
    }
};

#define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn)

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

{
    PROFILE_BLOCK("Some time");
    // your code or function
}

Это похоже на RAII по объему

ПРИМЕЧАНИЕ это не мое, но я подумал, что это уместно здесь


источник
1
в том числе пропавших
Степан Яковенко
9
#include<time.h> // for clock
#include<math.h> // for fmod
#include<cstdlib> //for system
#include <stdio.h> //for delay

using namespace std;

int main()
{


   clock_t t1,t2;

   t1=clock(); // first time capture

   // Now your time spanning loop or code goes here
   // i am first trying to display time elapsed every time loop runs

   int ddays=0; // d prefix is just to say that this variable will be used for display
   int dhh=0;
   int dmm=0;
   int dss=0;

   int loopcount = 1000 ; // just for demo your loop will be different of course

   for(float count=1;count<loopcount;count++)
   {

     t2=clock(); // we get the time now

     float difference= (((float)t2)-((float)t1)); // gives the time elapsed since t1 in milliseconds

    // now get the time elapsed in seconds

    float seconds = difference/1000; // float value of seconds
    if (seconds<(60*60*24)) // a day is not over
    {
        dss = fmod(seconds,60); // the remainder is seconds to be displayed
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the remainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= hours;  // the hours to be displayed
        ddays=0;
    }
    else // we have reached the counting of days
    {
        float days = seconds/(24*60*60);
        ddays = (int)(days);
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the rmainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= fmod (hours,24);  // the hours to be displayed

    }

    cout<<"Count Is : "<<count<<"Time Elapsed : "<<ddays<<" Days "<<dhh<<" hrs "<<dmm<<" mins "<<dss<<" secs";


    // the actual working code here,I have just put a delay function
    delay(1000);
    system("cls");

 } // end for loop

}// end of main 
Eskay
источник
3
Хотя ваш ответ приветствуется, мы предпочитаем преамбулу, содержащую краткое описание кода. Спасибо.
Кев
2
Это не прошедшее время, а время процессора.
JonnyJD
8

Значения, напечатанные вашей второй программой, представляют собой секунды и микросекунды.

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs
Дидье Троссет
источник
8
#include <ctime>
#include <cstdio>
#include <iostream>
#include <chrono>
#include <sys/time.h>
using namespace std;
using namespace std::chrono;

void f1()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();
  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  double dif = duration_cast<nanoseconds>( t2 - t1 ).count();
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f2()
{
  timespec ts1,ts2;
  clock_gettime(CLOCK_REALTIME, &ts1);
  clock_gettime(CLOCK_REALTIME, &ts2);
  double dif = double( ts2.tv_nsec - ts1.tv_nsec );
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f3()
{
  struct timeval t1,t0;
  gettimeofday(&t0, 0);
  gettimeofday(&t1, 0);
  double dif = double( (t1.tv_usec-t0.tv_usec)*1000);
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f4()
{
  high_resolution_clock::time_point t1 , t2;
  double diff = 0;
  t1 = high_resolution_clock::now() ;
  for(int i = 1; i <= 10 ; i++)
  {
    t2 = high_resolution_clock::now() ;
    diff+= duration_cast<nanoseconds>( t2 - t1 ).count();
    t1 = t2;
  }
  printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f5()
{
  timespec ts1,ts2;
  double diff = 0;
  clock_gettime(CLOCK_REALTIME, &ts1);
  for(int i = 1; i <= 10 ; i++)
  {
    clock_gettime(CLOCK_REALTIME, &ts2);
    diff+= double( ts2.tv_nsec - ts1.tv_nsec );
    ts1 = ts2;
  }
  printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f6()
{
  struct timeval t1,t2;
  double diff = 0;
  gettimeofday(&t1, 0);
  for(int i = 1; i <= 10 ; i++)
  {
    gettimeofday(&t2, 0);
    diff+= double( (t2.tv_usec-t1.tv_usec)*1000);
    t1 = t2;
  }
  printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

int main()
{
  //  f1();
  //  f2();
  //  f3();
  f6();
  f4();
  f5();
  return 0;
}
Аканша Гупта
источник
4

C ++ std :: chrono имеет явное преимущество кроссплатформенности. Тем не менее, он также вносит значительные накладные расходы по сравнению с POSIX clock_gettime (). На моем Linux-компьютере все std::chrono::xxx_clock::now()разновидности работают примерно одинаково:

std::chrono::system_clock::now()
std::chrono::steady_clock::now()
std::chrono::high_resolution_clock::now()

Хотя POSIX clock_gettime(CLOCK_MONOTONIC, &time)должен быть таким же, какsteady_clock::now() но он более чем в 3 раза быстрее!

Вот мой тест, для полноты.

#include <stdio.h>
#include <chrono>
#include <ctime>

void print_timediff(const char* prefix, const struct timespec& start, const 
struct timespec& end)
{
    double milliseconds = end.tv_nsec >= start.tv_nsec
                        ? (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3
                        : (start.tv_nsec - end.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec - 1) * 1e3;
    printf("%s: %lf milliseconds\n", prefix, milliseconds);
}

int main()
{
    int i, n = 1000000;
    struct timespec start, end;

    // Test stopwatch
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i) {
        struct timespec dummy;
        clock_gettime(CLOCK_MONOTONIC, &dummy);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("clock_gettime", start, end);

    // Test chrono system_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::system_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::system_clock::now", start, end);

    // Test chrono steady_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::steady_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::steady_clock::now", start, end);

    // Test chrono high_resolution_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::high_resolution_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::high_resolution_clock::now", start, end);

    return 0;
}

И это вывод, который я получаю при компиляции с gcc7.2 -O3:

clock_gettime: 24.484926 milliseconds
chrono::system_clock::now: 85.142108 milliseconds
chrono::steady_clock::now: 87.295347 milliseconds
chrono::high_resolution_clock::now: 84.437838 milliseconds
Алексей Полонский
источник
3

time(NULL)Вызов функции возвращает количество секунд , прошедшее с момента EPOC: 1 января 1970 года Возможно , что вы имеете в виду , чтобы сделать , это взять разницу между двумя отметками:

size_t start = time(NULL);
doSomthing();
doSomthingLong();

printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);
wilhelmtell
источник
3

Как уже отмечали другие, функция time () в стандартной библиотеке C не имеет разрешения лучше одной секунды. Похоже, единственной полностью переносимой функцией C, которая может обеспечить лучшее разрешение, является clock (), но она измеряет время процессора, а не время настенных часов. Если кто-то ограничен платформой POSIX (например, Linux), то функция clock_gettime () - хороший выбор.

Начиная с C ++ 11 доступны гораздо лучшие средства синхронизации, которые предлагают лучшее разрешение в форме, которая должна быть очень переносимой для разных компиляторов и операционных систем. Точно так же библиотека boost :: datetime предоставляет хорошие классы синхронизации высокого разрешения, которые должны быть легко переносимыми.

Одной из проблем при использовании любого из этих средств является задержка, вызванная запросом системных часов. Из экспериментов с clock_gettime (), boost :: datetime и std :: chrono, эта задержка может легко составлять несколько микросекунд. Таким образом, при измерении длительности любой части вашего кода вы должны учитывать наличие ошибки измерения примерно такого размера или пытаться каким-то образом исправить эту нулевую ошибку. В идеале вам может потребоваться собрать несколько измерений времени, затраченного вашей функцией, и вычислить среднее или максимальное / минимальное время, затраченное на несколько прогонов.

Чтобы помочь решить все эти проблемы переносимости и сбора статистики, я разработал библиотеку cxx-rtimers, доступную на Github, которая пытается предоставить простой API для блоков синхронизации кода C ++, вычисления нулевых ошибок и отчетности по статистике из встроенных таймеров. в вашем коде. Если у вас есть компилятор C ++ 11, вы просто #include <rtimers/cxx11.hpp>используете что-то вроде:

void expensiveFunction() {
    static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
    auto scopedStartStop = timer.scopedStart();
    // Do something costly...
}

При выходе из программы вы получите сводную статистику по времени, записанную в std :: cerr, такую ​​как:

Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)

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

Если вы хотите использовать специфичные для Linux функции синхронизации, вы можете #include <rtimers/posix.hpp>или, если у вас есть библиотеки Boost, но более старый компилятор C ++, вы можете это сделать #include <rtimers/boost.hpp>. Существуют также версии этих классов таймеров, которые могут собирать статистическую информацию о времени из разных потоков. Существуют также методы, позволяющие оценить нулевую ошибку, связанную с двумя непосредственно последовательными запросами системных часов.

РВП
источник
2

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

Майк Веллер
источник
2

Из того, что видно, tv_sec хранит прошедшие секунды, в то время как tv_usec хранит прошедшие отдельно микросекунды. И они не являются обращением друг друга. Следовательно, они должны быть изменены на соответствующую единицу и добавлены, чтобы получить общее время, прошедшее.

struct timeval startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

printf("**time taken in microseconds = %ld\n",
    (endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec))
    );
Сафар Лигаль
источник
2

В linux clock_gettime () - один из лучших вариантов. Вы должны связать библиотеку в реальном времени (-lrt).

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

#define BILLION  1000000000L;

int main( int argc, char **argv )
  {
    struct timespec start, stop;
    double accum;

    if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    system( argv[1] );

    if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    accum = ( stop.tv_sec - start.tv_sec )
          + ( stop.tv_nsec - start.tv_nsec )
            / BILLION;
    printf( "%lf\n", accum );
    return( EXIT_SUCCESS );
  }
cloudrain21
источник
2

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

Таким образом, я могу измерить время простоя блока кода, просто создав экземпляр одного из этих объектов в начале рассматриваемого блока кода (в действительности функции или любой области видимости), а затем позволяя деструктору экземпляров измерять время, прошедшее с момента строительство, когда экземпляр выходит за рамки. Вы можете найти полный пример здесь, но структура очень проста:

template <typename clock_t = std::chrono::steady_clock>
struct scoped_timer {
  using duration_t = typename clock_t::duration;
  const std::function<void(const duration_t&)> callback;
  const std::chrono::time_point<clock_t> start;

  scoped_timer(const std::function<void(const duration_t&)>& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  scoped_timer(std::function<void(const duration_t&)>&& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  ~scoped_timer() { callback(clock_t::now() - start); }
};

Структура перезвонит вам по предоставленному функтору, когда он выйдет из области видимости, чтобы вы могли что-то сделать с информацией о времени (распечатать или сохранить ее или что-то еще). Если вам нужно сделать что - то еще более сложными вы можете использовать даже std::bindс std::placeholdersобратным вызовом функции с большим количеством аргументов.

Вот быстрый пример его использования:

void test(bool should_throw) {
  scoped_timer<> t([](const scoped_timer<>::duration_t& elapsed) {
    auto e = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(elapsed).count();
    std::cout << "took " << e << "ms" << std::endl;
  });

  std::this_thread::sleep_for(std::chrono::seconds(1));

  if (should_throw)
    throw nullptr;

  std::this_thread::sleep_for(std::chrono::seconds(1));
}

Если вы хотите быть более взвешенным, вы также можете использовать newиdelete явно запускать и останавливать таймер, не полагаясь на то, что он сделает это за вас.

Кевин Крейзер
источник
1

Они одинаковы, потому что ваша функция doSomething происходит быстрее, чем гранулярность таймера. Пытаться:

printf ("**MyProgram::before time= %ld\n", time(NULL));

for(i = 0; i < 1000; ++i) {
    doSomthing();
    doSomthingLong();
}

printf ("**MyProgram::after time= %ld\n", time(NULL));
kibibu
источник
1

Причина, по которой оба значения одинаковы, заключается в том, что ваша длинная процедура не занимает столько времени - менее одной секунды. Вы можете попробовать просто добавить длинный цикл (for (int i = 0; i <100000000; i ++);) в конце функции, чтобы убедиться, что это проблема, тогда мы можем перейти оттуда ...

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

Давид Божьяк
источник
1

Я обычно использую следующее:

#include <chrono>
#include <type_traits>

using perf_clock = std::conditional<
    std::chrono::high_resolution_clock::is_steady,
    std::chrono::high_resolution_clock,
    std::chrono::steady_clock
>::type;

using floating_seconds = std::chrono::duration<double>;

template<class F, class... Args>
floating_seconds run_test(Func&& func, Args&&... args)
{
   const auto t0 = perf_clock::now();
   std::forward<Func>(func)(std::forward<Args>(args)...);
   return floating_seconds(perf_clock::now() - t0);
} 

Это то же самое, что предложил @ nikos-athanasiou, за исключением того, что я избегаю использования нестационарных часов и использую плавающее число секунд в качестве продолжительности.

oliora
источник
1
На этом переключателе типов : Обычно high_resolution_clockэто typedef для либо system_clockили steady_clock. Таким образом, чтобы проследить, что std::conditionalесли is_steadyчасть истинна, тогда вы выбираете, high_resolution_clockкоторый является (typedef) steady_clock. Если это неверно, вы выбираете steady_clockснова. Просто используйте steady_clockс самого начала ...
Никос Атанасиу
@ nikos-athanasiou Я полностью согласен с комментарием 5gon12eder о том, что «типичный» случай не требуется стандартом, поэтому некоторые STL могут быть реализованы другим способом. Я предпочитаю, чтобы мой код был более общим и не связанным с деталями реализации.
oliora
Это не требуется , но в явном виде указано в 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. Причина заключается в следующем: high_resolution_clockпредставляет часы с самым коротким периодом тиков, поэтому, независимо от реализации, у нее есть два варианта: постоянный или нет. Какой бы выбор мы ни сделали, сказать, что реализация будет отличаться от двух других тактовых импульсов, все равно, что сказать, что у нас есть лучшая реализация для устойчивых (или нет) тактовых импульсов, которые мы решили не использовать (для устойчивых или нет тактовых генераторов). Знать, как хорошо, знать, почему лучше
Никос Атанасиу
@ nikos-athanasiou Я бы предпочел быть на 100% безопасным, особенно когда это не стоило мне затрат времени выполнения и необнаружимых затрат времени компиляции. Вы можете положиться на «может» и предположения, если хотите.
Олиора
В отличие от моего друга, это вы, что полагается на «май», но устраивать себя. Если вы хотите быть на 100% уверены и продолжаете писать это, вы должны также найти способ для вас и пользователей вашего кода избежать непередаваемого смешивания моментов времени разных часов (если этот тип переключателя приобретает смысл, он будет вести себя по-разному на разных платформах). Радоваться, веселиться!
Никос Атанасиу
0

В ответ на три конкретных вопроса ОП .

«Что я не понимаю, так это то, почему значения до и после одинаковы? »

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

Следующий пример использует gettimeofday()который заполняет эту структуру

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};

и второй вопрос спрашивает: «Как я могу прочитать результат **time taken = 0 26339? Означает ли это 26 339 наносекунд = 26,3 мс?»

Мой второй ответ: время составляет 0 секунд и 26339 микросекунд, то есть 0,026339 секунд, что подтверждает первый пример, выполненный менее чем за 1 секунду.

Третий вопрос спрашивает: « А что **time taken = 4 45025, это означает 4 секунды и 25 мс?»

Мой третий ответ - это 4 секунды и 45025 микросекунд, то есть 4,045025 секунд, что показывает, что OP изменил задачи, выполняемые двумя функциями, которые он ранее рассчитывал.

Флюгер
источник
0
#include <ctime>
#include <functional>

using namespace std;

void f() {
  clock_t begin = clock();

  // ...code to measure time...

  clock_t end = clock();

  function<double(double, double)> convtime = [](clock_t begin, clock_t end)
  {
     return double(end - begin) / CLOCKS_PER_SEC;
  };

  printf("Elapsed time: %.2g sec\n", convtime(begin, end));

}

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

TarmoPikaro
источник
0

Я создал класс для автоматического измерения прошедшего времени. Пожалуйста, проверьте код (c ++ 11) по этой ссылке: https://github.com/sonnt174/Common/blob/master/time_measure.h

Пример использования класса TimeMeasure:

void test_time_measure(std::vector<int> arr) {
  TimeMeasure<chrono::microseconds> time_mea;  // create time measure obj
  std::sort(begin(arr), end(arr));
}
Сирн Нгуен Чыонг
источник
Мне нравится ваше печатное заявление с единицами. Что нужно для переноса вашего кода на gcc и clang? ( wandbox.org )
Говард Хиннант
1
@HowardHinnant: спасибо за обращение, я также обновил код для gcc и clang.
Сирн Нгуен Чыонг
0

Matlab ароматный!

ticзапускает секундомер для измерения производительности. Функция записывает внутреннее время при выполнении команды tic. Отображение прошедшего времени с помощью tocфункции.

#include <iostream>
#include <ctime>
#include <thread>
using namespace std;

clock_t START_TIMER;

clock_t tic()
{
    return START_TIMER = clock();
}

void toc(clock_t start = START_TIMER)
{
    cout
        << "Elapsed time: "
        << (clock() - start) / (double)CLOCKS_PER_SEC << "s"
        << endl;
}

int main()
{
    tic();
    this_thread::sleep_for(2s);
    toc();

    return 0;
}
Яс
источник
-4

Вы можете использовать библиотеку SFML , которая является простой и быстрой мультимедийной библиотекой. Он включает в себя множество полезных и четко определенных классов, таких как Clock, Socket, Sound, Graphics и т. Д. Он очень прост в использовании и настоятельно рекомендуется.

Это пример для этого вопроса.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
cloudrain21
источник