Usando apenas ANSI C, existe alguma maneira de medir o tempo com precisão de milissegundos ou mais? Eu estava navegando no time.h, mas só encontrei segundas funções de precisão.
c
portability
time-precision
corto
fonte
fonte
Respostas:
Não há nenhuma função ANSI C que ofereça resolução melhor que 1 segundo, mas a função POSIX
gettimeofday
fornece resolução de microssegundos. A função de relógio mede apenas a quantidade de tempo que um processo passou executando e não é precisa em muitos sistemas.Você pode usar esta função assim:
Isso retorna
Time elapsed: 1.000870
na minha máquina.fonte
timeval::tv_usec
está sempre abaixo de um segundo, está em loop. Ou seja, para ter diferenças de tempo maiores que 1 segundo, você deve:long usec_diff = (e.tv_sec - s.tv_sec)*1000000 + (e.tv_usec - s.tv_usec);
timersub
incorporada na função. Podemos usartval_result
valores (tv_sec e tv_usec) como estão.fonte
CLOCKS_PER_SEC / 1000
pode ser inexata, o que poderia afetar o resultado final (embora, na minha experiênciaCLOCKS_PER_SEC
, sempre tenha sido um múltiplo de 1000). Fazer(1000 * clock()) / CLOCKS_PER_SEC
é menos suscetível à inexatidão de divisão, mas, por outro lado, é mais suscetível ao transbordamento. Apenas algumas questões a considerar.Eu sempre uso a função clock_gettime (), retornando a hora do relógio CLOCK_MONOTONIC. O tempo retornado é a quantidade de tempo, em segundos e nanossegundos, desde algum ponto não especificado no passado, como a inicialização do sistema na época.
fonte
clock_gettime(CLOCK_MONOTONIC, ...)
e há até a macro de teste de recursos_POSIX_MONOTONIC_CLOCK
.Implementando uma solução portátil
Como já foi mencionado aqui que não existe uma solução ANSI adequada com precisão suficiente para o problema de medição de tempo, quero escrever sobre as maneiras de obter uma solução de medição de tempo portátil e, se possível, de alta resolução.
Relógio monotônico x time stamp
De um modo geral, existem duas maneiras de medir o tempo:
O primeiro usa um contador de relógio monotônico (às vezes chamado de contador de ticks), que conta os ticks com uma frequência predefinida; portanto, se você tiver um valor de ticks e a frequência for conhecida, poderá converter facilmente os ticks em tempo decorrido. Na verdade, não é garantido que um relógio monotônico reflita a hora atual do sistema de qualquer forma; ele também pode contar tiques desde a inicialização do sistema. Mas garante que um relógio sempre funcione de maneira crescente, independentemente do estado do sistema. Normalmente, a frequência está ligada a uma fonte de alta resolução de hardware, por isso fornece alta precisão (depende do hardware, mas a maioria do hardware moderno não tem problemas com fontes de relógio de alta resolução).
A segunda maneira fornece um valor de hora (data) com base no valor atual do relógio do sistema. Ele também pode ter uma alta resolução, mas tem uma grande desvantagem: esse tipo de valor de hora pode ser afetado por diferentes ajustes de hora do sistema, ou seja, alteração de fuso horário, alteração de horário de verão (DST), atualização do servidor NTP, hibernação do sistema etc. em. Em algumas circunstâncias, você pode obter um valor de tempo decorrido negativo que pode levar a um comportamento indefinido. Na verdade, esse tipo de fonte de tempo é menos confiável que a primeira.
Portanto, a primeira regra na medição do intervalo de tempo é usar um relógio monotônico, se possível. Geralmente, possui alta precisão e é confiável por design.
Estratégia de fallback
Ao implementar uma solução portátil, vale a pena considerar uma estratégia de fallback: use um relógio monotônico, se disponível, e o fallback para registro de data e hora se aproximar, se não houver um relógio monotônico no sistema.
janelas
Existe um ótimo artigo chamado Adquirindo carimbos de data / hora de alta resolução no MSDN sobre medição de tempo no Windows, que descreve todos os detalhes que você precisa saber sobre o suporte de software e hardware. Para adquirir um carimbo de data / hora de alta precisão no Windows, você deve:
consulte uma frequência do timer (ticks por segundo) com QueryPerformanceFrequency :
A frequência do timer é fixada na inicialização do sistema, portanto, você precisa obtê-la apenas uma vez.
consulte o valor atual dos ticks com QueryPerformanceCounter :
dimensione os ticks para o tempo decorrido, ou seja, para microssegundos:
De acordo com a Microsoft, você não deve ter problemas com essa abordagem no Windows XP e versões posteriores na maioria dos casos. Mas você também pode usar duas soluções de fallback no Windows:
GetTickCount
, mas está disponível a partir do Windows Vista e superior.OS X (macOS)
O OS X (macOS) possui suas próprias unidades de tempo absoluto, que representam um relógio monotônico. A melhor maneira de começar é o artigo da Apple, Perguntas e respostas técnicas QA1398: Unidades de tempo absoluto do Mach, que descreve (com os exemplos de código) como usar a API específica do Mach para obter ticks monotônicos. Também existe uma pergunta local sobre ela chamada alternativa clock_gettime no Mac OS X que, no final, pode deixar você um pouco confuso sobre o que fazer com o possível excesso de valor, porque a frequência do contador é usada na forma de numerador e denominador. Então, um pequeno exemplo de como obter o tempo decorrido:
obtenha o numerador e o denominador da frequência do relógio:
Você precisa fazer isso apenas uma vez.
consulte o valor atual do tick com
mach_absolute_time
:dimensione os ticks para o tempo decorrido, ou seja, para microssegundos, usando numerador e denominador consultados anteriormente:
A principal idéia para evitar um transbordamento é diminuir a escala dos ticks com a precisão desejada antes de usar o numerador e o denominador. Como a resolução inicial do timer é em nanossegundos, nós a dividimos
1000
para obter microssegundos. Você pode encontrar a mesma abordagem usada no time_mac.c do Chromium . Se você realmente precisa de uma precisão de nanossegundos, considere a leitura de Como posso usar o mach_absolute_time sem transbordar? .Linux e UNIX
A
clock_gettime
chamada é o seu melhor caminho em qualquer sistema compatível com POSIX. Ele pode consultar a hora de diferentes fontes de relógio, e a que precisamos éCLOCK_MONOTONIC
. Nem todos os sistemas comclock_gettime
suporteCLOCK_MONOTONIC
, portanto, a primeira coisa que você precisa fazer é verificar sua disponibilidade:_POSIX_MONOTONIC_CLOCK
for definido com um valor>= 0
, significa queCLOCK_MONOTONIC
está disponível;se
_POSIX_MONOTONIC_CLOCK
estiver definido0
, significa que você deve verificar adicionalmente se funciona em tempo de execução, sugiro usarsysconf
:O uso de
clock_gettime
é bastante simples:obtenha o valor do tempo:
Reduzi o tempo para microssegundos aqui.
calcule a diferença com o valor de tempo anterior recebido da mesma maneira:
A melhor estratégia de fallback é usar a
gettimeofday
chamada: não é monotônica, mas fornece uma resolução bastante boa. A idéia é a mesma que comclock_gettime
, mas para obter um valor de tempo, você deve:Novamente, o valor do tempo é reduzido para microssegundos.
SGI IRIX
O IRIX tem a
clock_gettime
ligação, mas faltaCLOCK_MONOTONIC
. Em vez disso, possui sua própria fonte de relógio monotônico definida como aCLOCK_SGI_CYCLE
qual você deve usar em vez deCLOCK_MONOTONIC
comclock_gettime
.Solaris e HP-UX
O Solaris possui sua própria interface de timer de alta resolução,
gethrtime
que retorna o valor atual do timer em nanossegundos. Embora as versões mais recentes do Solaris possam terclock_gettime
, você pode seguirgethrtime
se precisar dar suporte a versões antigas do Solaris.O uso é simples:
O HP-UX não possui
clock_gettime
, mas suporta osgethrtime
quais você deve usar da mesma maneira que no Solaris.BeOS
O BeOS também possui sua própria interface de timer de alta resolução,
system_time
que retorna o número de microssegundos decorridos desde que o computador foi inicializado.Exemplo de uso:
OS / 2
O OS / 2 possui sua própria API para recuperar registros de data e hora de alta precisão:
consulte uma frequência do timer (ticks por unidade) com
DosTmrQueryFreq
(para compilador GCC):consulte o valor atual dos ticks com
DosTmrQueryTime
:dimensione os ticks para o tempo decorrido, ou seja, para microssegundos:
Implementação de exemplo
Você pode dar uma olhada na biblioteca plibsys , que implementa todas as estratégias descritas acima (consulte ptimeprofiler * .c para obter detalhes).
fonte
timespec_get
: stackoverflow.com/a/36095407/895245timespec_get
não é monotônico.timespec_get
de C11Retorna em nanossegundos, arredondado para a resolução da implementação.
Parece um ripoff ANSI do POSIX '
clock_gettime
.Exemplo: a
printf
é feito a cada 100ms no Ubuntu 15.10:O rascunho padrão do C11 N1570 7.27.2.5 "A função timespec_get diz":
O C ++ 11 também recebeu
std::chrono::high_resolution_clock
: Temporizador de alta resolução entre plataformas C ++implementação glibc 2.21
Pode ser encontrado em
sysdeps/posix/timespec_get.c
:tão claramente:
única
TIME_UTC
é atualmente suportadaencaminha para
__clock_gettime (CLOCK_REALTIME, ts)
, que é uma API POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.htmlO Linux x86-64 possui uma
clock_gettime
chamada de sistema.Observe que este não é um método de micro-benchmarking à prova de falhas porque:
man clock_gettime
diz que essa medida pode ter descontinuidades se você alterar alguma configuração de hora do sistema enquanto o programa é executado. É claro que esse deve ser um evento raro e você poderá ignorá-lo.isso mede o tempo da parede; portanto, se o planejador decidir esquecer sua tarefa, ele parecerá ser executado por mais tempo.
Por essas razões
getrusage()
pode ser uma ferramenta melhor de avaliação comparativa POSIX, apesar da menor precisão máxima de microssegundos.Mais informações em: Medir o tempo no Linux - hora x relógio x getrusage x clock_gettime x gettimeofday x timespec_get?
fonte
A melhor precisão possível é através do uso da instrução "rdtsc" somente no x86, que pode fornecer resolução no nível do relógio (é claro que é necessário levar em conta o custo da chamada rdtsc, que pode ser facilmente medida em inicialização do aplicativo).
O principal problema aqui é medir o número de relógios por segundo, o que não deve ser muito difícil.
fonte
A resposta aceita é boa o suficiente. Mas minha solução é mais simples. Apenas teste no Linux, use o gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0.
Além disso
gettimeofday
, otv_sec
é a parte do segundo e otv_usec
é microssegundos , não milissegundos .Imprimir:
1522139691342 1522139692342
exatamente um segundo.fonte
Sob janelas:
fonte