C++ получение миллисекунд времени на Linux-clock (), похоже, не работает должным образом


На Windows, clock() возвращает время в миллисекундах, но на этом поле Linux, над которым я работаю, он округляет его до ближайшей 1000, поэтому точность только до "второго" уровня, а не до уровня миллисекунд.

Я нашел решение с Qt, используя QTime класса, создание экземпляра объекта и вызов start() на него, то вызов elapsed() чтобы получить количество миллисекунд прошло.

мне повезло, потому что я работаю с Qt для начала, но я хотел бы решение, которое не зависит от сторонних библиотек,

нет стандартного способа сделать это?

обновление

пожалуйста, не рекомендую Boost ..

если Boost и Qt могут это сделать, конечно, это не магия, должно быть что-то стандартное, что они используют!

16 97

16 ответов:

вы можете использовать gettimeofday в начале и конце вашего метода, а затем различать две возвращаемые структуры. Вы получите структуру, как показано ниже:

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    struct timeval start, end;

    long mtime, seconds, useconds;    

    gettimeofday(&start, NULL);
    usleep(2000);
    gettimeofday(&end, NULL);

    seconds  = end.tv_sec  - start.tv_sec;
    useconds = end.tv_usec - start.tv_usec;

    mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;

    printf("Elapsed time: %ld milliseconds\n", mtime);

    return 0;
}

обратите внимание:clock тут не измерения времени. Это означает, что если ваша программа занимает 5 секунд, clock не будет измерять 5 секунд обязательно, но может больше (ваша программа может запускать несколько потоков и поэтому может потреблять больше процессора, чем в реальном времени) или меньше. Он измеряет приближение процессорного времени используется. Чтобы увидеть разницу рассмотрим этот код

#include <iostream>
#include <ctime>
#include <unistd.h>

int main() {
    std::clock_t a = std::clock();
    sleep(5); // sleep 5s
    std::clock_t b = std::clock();

    std::cout << "difference: " << (b - a) << std::endl;
    return 0;
}

он выводит на моей системе

$ difference: 0

потому что все, что мы сделали спать и не использовать время процессора! Однако, используя gettimeofday мы получаем то, что хотим (?)

#include <iostream>
#include <ctime>
#include <unistd.h>
#include <sys/time.h>

int main() {
    timeval a;
    timeval b;

    gettimeofday(&a, 0);
    sleep(5); // sleep 5s
    gettimeofday(&b, 0);

    std::cout << "difference: " << (b.tv_sec - a.tv_sec) << std::endl;
    return 0;
}

выходы на моей системе

$ difference: 5

Если вам нужно больше точности, но хотите сделать процессорного времени, то вы можете рассмотреть возможность использования

я также рекомендую инструменты, предлагаемые Boost. Либо упомянутый таймер наддува, либо взломать что-то из наддува.DateTime или есть новая предлагаемая библиотека в песочнице -импульс.Хроно: этот последний будет заменой таймера и будет иметь:

  • утилиты времени стандартной библиотеки C++0x, в том числе:
    • шаблон класса duration
    • шаблон класса time_point
    • часы:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • шаблон класса timer, С typedefs:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • процесс часы и таймеры:
    • process_clock, захват реального, пользовательского процессора и системного процессора.
    • process_timer, захват прошедшего реального, пользователь-CPU, а система-CPU раз.
    • run_timer, удобная отчетность |process_timer / результатов.
  • рациональная арифметика времени компиляции стандартной библиотеки C++0x.

вот источник из списка объектов

Я написал Timer класса на основе ответ CTT. Его можно использовать следующим образом:

Timer timer = Timer();
timer.start();
/* perform task */
double duration = timer.stop();
timer.printTime(duration);

вот его реализация:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
using namespace std;

class Timer {
private:

    timeval startTime;

public:

    void start(){
        gettimeofday(&startTime, NULL);
    }

    double stop(){
        timeval endTime;
        long seconds, useconds;
        double duration;

        gettimeofday(&endTime, NULL);

        seconds  = endTime.tv_sec  - startTime.tv_sec;
        useconds = endTime.tv_usec - startTime.tv_usec;

        duration = seconds + useconds/1000000.0;

        return duration;
    }

    static void printTime(double duration){
        printf("%5.6f seconds\n", duration);
    }
};

Если вам не нужен код, чтобы быть переносимым на старые unices, вы можете использовать clock_gettime (), который даст вам время в наносекунд (Если ваш процессор поддерживает эту резолюцию). Это POSIX, но с 2001 года.

clock () имеет часто довольно паршивое разрешение. Если вы хотите измерить время на миллисекундном уровне, один из вариантов-использовать clock_gettime (), как описано в этом вопросе.

(помните, что вам нужно связаться с-lrt на Linux).

С C++11 и std::chrono::high_resolution_clock можно сделать так:

#include <iostream>
#include <chrono>
#include <thread>
typedef std::chrono::high_resolution_clock Clock;

int main()
{
    std::chrono::milliseconds three_milliseconds{3};

    auto t1 = Clock::now();
    std::this_thread::sleep_for(three_milliseconds);
    auto t2 = Clock::now();

    std::cout << "Delta t2-t1: " 
              << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count()
              << " milliseconds" << std::endl;
}

выход:

Delta t2-t1: 3 milliseconds

ссылка на демо: http://cpp.sh/2zdtu

clock () не возвращает миллисекунды или секунды на linux. Обычно clock () возвращает микросекунды в системе linux. Правильный способ интерпретировать значение, возвращаемое clock (), состоит в том, чтобы разделить его на CLOCKS_PER_SEC, чтобы выяснить, сколько времени прошло.

Это должно работать...протестировано на mac...

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

int main() {
        struct timeval tv;
        struct timezone tz;
        struct tm *tm;
        gettimeofday(&tv,&tz);
        tm=localtime(&tv.tv_sec);
        printf("StartTime: %d:%02d:%02d %d \n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);
}

да...запустите его дважды и вычесть...

в стандарте POSIX clock имеет свое возвращаемое значение, определенное в терминах символа CLOCKS_PER_SEC, и реализация может определить это любым удобным способом. Под Linux мне повезло с

gettimeofday-проблема в том, что будет иметь более низкие значения, если вы измените аппаратные часы (например, с NTP) Boost-недоступен для данного проекта clock () - обычно возвращает 4 байта целого числа, что означает, что его низкая емкость, и через некоторое время он возвращает отрицательные числа.

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

class MyAlarm {
static int64_t tiempo;
static bool running;
public:
static int64_t getTime() {return tiempo;};
static void callback( int sig){
    if(running){
        tiempo+=10L;
    }
}
static void run(){ running = true;}
};

int64_t MyAlarm::tiempo = 0L;
bool MyAlarm::running = false;

чтобы обновить его я использовать setitimer:

int main(){
struct sigaction sa; 
struct itimerval timer; 

MyAlarm::run();
memset (&sa, 0, sizeof (sa)); 
sa.sa_handler = &MyAlarm::callback; 

sigaction (SIGALRM, &sa, NULL); 


timer.it_value.tv_sec = 0; 
timer.it_value.tv_usec = 10000; 



timer.it_interval.tv_sec = 0; 
timer.it_interval.tv_usec = 10000; 


setitimer (ITIMER_REAL, &timer, NULL); 
.....

посмотреть setitimer и ITIMER_VIRTUAL и образом, получается, что.

Не используйте функции сигнализации или ualarm, у вас будет низкая точность, когда ваш процесс получит тяжелую работу.

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

как обновление, появляется, что на Windows clock () измеряет время настенных часов (с точностью CLOCKS_PER_SEC)

 http://msdn.microsoft.com/en-us/library/4e2ess30(VS.71).aspx

в то время как на Linux он измеряет процессорное время между ядрами, используемыми текущим процессом

http://www.manpagez.com/man/3/clock

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

Мне нравится метод Hola Soy не использовать gettimeofday (). Это случилось со мной на работающем сервере администратор изменил часовой пояс. Часы были обновлены, чтобы показать то же самое (правильное) локальное значение. Это привело к тому, что функция time() и gettimeofday() сдвинулись на 2 часа, и все метки времени в некоторых службах застряли.

я написал C++ класс с помощью timeb.

#include <sys/timeb.h>
class msTimer 
{
public:
    msTimer();
    void restart();
    float elapsedMs();
private:
    timeb t_start;
};

функции-члены:

msTimer::msTimer() 
{ 
    restart(); 
}

void msTimer::restart() 
{ 
    ftime(&t_start); 
}

float msTimer::elapsedMs() 
{
    timeb t_now;
    ftime(&t_now);
    return (float)(t_now.time - t_start.time) * 1000.0f +
           (float)(t_now.millitm - t_start.millitm);
}

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

#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char** argv) 
{
    msTimer t;
    for (int i = 0; i < 5000000; i++)
        ;
    std::cout << t.elapsedMs() << endl;
    return 0;
}

выход на моем компьютере '19'. Точность msTimer класс имеет порядок миллисекунд. В приведенном выше примере использования общее время выполнения, занятое for-цикл отслеживается. На этот раз включалась операционная система, включающая и выключающая контекст выполнения main() из-за многозадачности.