Como faço para medir o tempo de execução de um comando na linha de comando do Windows?

Respostas:

113

Se você estiver usando o Windows 2003 (observe que o Windows Server 2008 e versões posteriores não são suportadas), poderá usar o Windows Server 2003 Resource Kit, que contém timeit.exe que exibe estatísticas detalhadas de execução. Aqui está um exemplo, cronometrando o comando "timeit -?":

C:\>timeit timeit -?
Invalid switch -?
Usage: TIMEIT [-f filename] [-a] [-c] [-i] [-d] [-s] [-t] [-k keyname | -r keyname] [-m mask] [commandline...]
where:        -f specifies the name of the database file where TIMEIT
                 keeps a history of previous timings.  Default is .\timeit.dat
              -k specifies the keyname to use for this timing run
              -r specifies the keyname to remove from the database.  If
                 keyname is followed by a comma and a number then it will
                 remove the slowest (positive number) or fastest (negative)
                 times for that keyname.
              -a specifies that timeit should display average of all timings
                 for the specified key.
              -i specifies to ignore non-zero return codes from program
              -d specifies to show detail for average
              -s specifies to suppress system wide counters
              -t specifies to tabular output
              -c specifies to force a resort of the data base
              -m specifies the processor affinity mask

Version Number:   Windows NT 5.2 (Build 3790)
Exit Time:        7:38 am, Wednesday, April 15 2009
Elapsed Time:     0:00:00.000
Process Time:     0:00:00.015
System Calls:     731
Context Switches: 299
Page Faults:      515
Bytes Read:       0
Bytes Written:    0
Bytes Other:      298

Você pode obter o TimeIt no Windows 2003 Resource Kit. Faça o download aqui .

Servy
fonte
7
Este kit tem problemas com windows 2008 de 64 bits e não funciona em 2008 R2
Artem
existe alguma maneira de medir também o tempo do kernel e / ou o tempo usado pelos subprocessos gerados?
Rogerdpack
38
Para sua informação, não acho que o tempo funcione no Windows 7 de 64 bits. Você recebe o erro "Não é possível consultar os dados de desempenho do sistema (c0000004). Em vez disso, use o" Measure-Command "do PowerShell como Casey.K sugere: stackoverflow.com/questions/673523/…
Michael La Voie
6
No Windows 7, vejo "'timeit' não é reconhecido como um comando interno ou externo, programa operável ou arquivo em lote".
Coronel Panic
3
Não vejo o comando no Windows 10, nem encontro facilmente um Resource Kit para Win 10. Alguém sabe como fazer isso com o 10?
Jay Imerman
469

Como alternativa, o Windows PowerShell possui um comando interno semelhante ao comando "time" do Bash. É chamado "Medida-Comando". Você precisará garantir que o PowerShell esteja instalado na máquina que o executa.

Exemplo de entrada:

Measure-Command {echo hi}

Saída de exemplo:

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 1318
TotalDays         : 1.52546296296296E-09
TotalHours        : 3.66111111111111E-08
TotalMinutes      : 2.19666666666667E-06
TotalSeconds      : 0.0001318
TotalMilliseconds : 0.1318
Casey.K
fonte
21
Esta é a melhor solução para usuários do Windows 7 como timeit.exe não parece suportar o Windows 7
Michael La Voie
14
Caso deseje usar comandos internos do (por exemplo: dir, eco, del, etc.), não se esqueça de inserir "cmd / c": Comando-Medida {cmd / c dir / sc: \ windows> nul}
precisa saber é o seguinte
7
Se você está aferição uma .exeno diretório atual, use o seguinte: Measure-Command { .\your.exe }. Aparentemente, o PowerShell não executa as coisas, a pwdmenos que seja explicitamente instruído.
Cristian Diaconescu
13
Irritantemente, ele esconde stdout.
Zitrax
13
Isso NÃO é uma ferramenta 'semelhante ao comando de tempo do Bash' . Mas é bom saber ... mas: ele não executa e retorna aos<stdout> resultados do comando entre colchetes!
Kurt Pfeifle
287

Se você quiser

  1. Para medir o tempo de execução até o centésimo de segundo em (formato hh: mm: ss.ff)
  2. Para não precisar baixar e instalar um pacote de recursos
  3. Para parecer um grande nerd do DOS (quem não gosta)

Tente copiar o seguinte script em um novo arquivo em lotes (por exemplo, timecmd.bat ):

@echo off
@setlocal

set start=%time%

:: Runs your command
cmd /c %*

set end=%time%
set options="tokens=1-4 delims=:.,"
for /f %options% %%a in ("%start%") do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f %options% %%a in ("%end%") do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 100

set /a hours=%end_h%-%start_h%
set /a mins=%end_m%-%start_m%
set /a secs=%end_s%-%start_s%
set /a ms=%end_ms%-%start_ms%
if %ms% lss 0 set /a secs = %secs% - 1 & set /a ms = 100%ms%
if %secs% lss 0 set /a mins = %mins% - 1 & set /a secs = 60%secs%
if %mins% lss 0 set /a hours = %hours% - 1 & set /a mins = 60%mins%
if %hours% lss 0 set /a hours = 24%hours%
if 1%ms% lss 100 set ms=0%ms%

:: Mission accomplished
set /a totalsecs = %hours%*3600 + %mins%*60 + %secs%
echo command took %hours%:%mins%:%secs%.%ms% (%totalsecs%.%ms%s total)

Uso

Se você colocar timecmd.bat em um diretório em seu caminho, poderá chamá-lo de qualquer lugar como este:

timecmd [your command]

Por exemplo

C:\>timecmd pause
Press any key to continue . . .
command took 0:0:1.18

Se você deseja fazer o redirecionamento de saída, pode citar o comando da seguinte maneira:

timecmd "dir c:\windows /s > nul"

Isso deve lidar com comandos que são executados antes e depois da meia-noite, mas a saída estará errada se o seu comando for executado por 24 horas ou mais.

Luke Sampson
fonte
9
substituir cmd / c% * por % * funciona, a menos que seu comando seja outro arquivo em lotes. Então você teria que fazer chamada timecmd other.bat
Jesse Chisholm
2
@JesseChisholm No Windows 8 (e eu li no Windows 7 também), você não precisa a chamada para .bat
Brian J
4
Por alguma razão, isso só me dá saída em segundos inteiros ... o que para mim é inútil. Quero dizer que corro timecmd pause, e sempre resulta em 1,00 seg, 2,00 seg, 4,00 seg ... até 0,00 seg! Windows 7.
Camilo Martin
9
@CamiloMartin e outros que tiveram isso (como eu) - você pode ter um código de idioma, que usa COMMA em vez de DOT para decimal. Portanto, nesse scrpit, mude delims=:.para delims=:.,e, em seguida, ele deve funcionar "de maneira geral".
Tomasz Gandor
5
Há um erro aritmético sério nesse script: Tente com: set start=10:10:10.10 set end=10:11:10.09E ele produzirá: command took 0:1:-1.99 (59.99s total) Você deve reverter a ordem das 4 linhas que fazem comparações "lss 0", para que o transporte progrida corretamente dos dígitos sexagesimais mínimos para os altos. Em seguida, a saída se torna: command took 0:0:59.99 (59.99s total)
Jean-François Larvoire
230

Hehe, a solução mais simples pode ser a seguinte:

echo %time%
YourApp.exe
echo %time%

Isso funciona em todos os Windows prontos para uso.


No caso de um aplicativo usar saída do console, pode ser conveniente armazenar o horário de início em uma variável temporária:

set startTime=%time%
YourApp.exe
echo Start Time: %startTime%
echo Finish Time: %time%
LietKynes
fonte
163
Você é louco?! Isso envolve fazer matemática, tipo, no seu cérebro. É por isso que inventamos os computadores, para evitar fazer coisas assim.
Luke Sampson
1
brilhante! Mesmo assim, para o tempo de CPU não realmente ajudar
Elias Saounkine
10
Ainda melhor (se o seu aplicativo espetos saída para o console): set startTime=%time% \n YourApp.exe \n echo Start Time: %startTime% \n echo Finish Time: %time% (Desculpe, não pude obter novas linhas no comentário)
Jono
1
@ LucasSampson, você pode usar setpara fazer as contas. ;-)Oh espera, deixa pra lá, você já fez isso abaixo.
Synetech
2
Não, esta é uma má opção. Isso indica a hora do relógio de parede, não a hora da CPU. Portanto, mesmo que sua linha de comando possa demorar apenas 100 ms, se houver outro aplicativo monopolizando a CPU, seu aplicativo poderá levar segundos (menos de 100x ou mais). De fato, se sua máquina estiver debatendo, você pode até esperar um minuto para que seu pequeno aplicativo de 100ms seja executado. Acompanhe o tempo da CPU, não o tempo do relógio de parede!
Ryan Shillington
102

Apenas uma pequena expansão da resposta da Casey.K sobre o uso Measure-Commanddo PowerShell :

  1. Você pode invocar o PowerShell no prompt de comando padrão, assim:

    powershell -Command "Measure-Command {echo hi}"
    
  2. Isso consumirá a saída padrão, mas você pode impedir isso adicionando | Out-Defaultassim do PowerShell:

    Measure-Command {echo hi | Out-Default}
    

    Ou em um prompt de comando:

    powershell -Command "Measure-Command {echo hi | Out-Default}"
    

Obviamente, você pode agrupar isso em um arquivo de script *.ps1ou *.bat.

Vladimir Veljkovic
fonte
1
E se o comando que queremos medir tiver aspas? Isso pode ser transformado em um script .bat nesse caso? Por exemplomeasureTime.bat "c:\program files\some dir\program.exe"
GetFree
53

A linha única que eu uso no Windows Server 2008 R2 é:

cmd /v:on /c "echo !TIME! & *mycommand* & echo !TIME!"

Enquanto mycommand não requer aspas (que parafusos com processamento citação de cmd). O /v:onobjetivo é permitir que os dois valores TIME diferentes sejam avaliados independentemente, e não uma vez na execução do comando.

Nathan Herring
fonte
Isso também não funcionará para os lotes de "spam", que substituem o rótulo da primeira vez e implicam que você substitua o computador que faz o cálculo, conforme observado em stackoverflow.com/questions/673523/…
Val
Normalmente, você pode escapar de aspas ^em cmd (like ^")
n611x007
2
Se você repetir o cmd / v: on pela segunda cronometragem, podemos até fazer com que meu comando contenha aspas. Exemplo: cmd /v:on /c echo !TIME! & echo "Quoted mycommand" & cmd /v:on /c echo !TIME!.
Maarten Pennings
8
Mais simples: echo %time% & *mycommand* & call echo %^time%. Veja também esta resposta .
Aacini 7/03/2017
Se o seu comando gerar muito, talvez seja mais fácil juntar as duas vezes:cmd /v:on /c "mycommand & echo begin=%time% endtime=!time!"
ZHANG Zikai
49

Se você tiver uma janela de comando aberta e chamar os comandos manualmente, poderá exibir um carimbo de data / hora em cada prompt, por exemplo

prompt $d $t $_$P$G

Dá-lhe algo como:

23.03.2009 15:45:50,77

C:\>

Se você tiver um pequeno script em lote que execute seus comandos, tenha uma linha vazia antes de cada comando, por exemplo

(linha vazia)

myCommand.exe

(próxima linha vazia)

myCommand2.exe

Você pode calcular o tempo de execução de cada comando pelas informações de tempo no prompt. O melhor seria provavelmente canalizar a saída para um arquivo de texto para análise posterior:

MyBatchFile.bat > output.txt
Treb
fonte
3
Pensei em ficar alguns anos atrás da discussão para agradecer por compartilhar o comando prompt. Eu já vi muitos truques de CMD (mais do tipo bash guy), mas este escapou ao meu conhecimento.
Steve Howard
Simples, elegante, sem instalação e sem gravar arquivos em lote para um comando de uma só vez e pode cronometrar cada etapa em um arquivo em lotes.
Matt
26

Como outros recomendam a instalação de coisas como freeware e PowerShell, você também pode instalar o Cygwin , que daria acesso a muitos comandos básicos do Unix, como o tempo :

abe@abe-PC:~$ time sleep 5

real    0m5.012s
user    0m0.000s
sys 0m0.000s

Não tenho certeza de quanto Cygwin sobrecarga acrescenta.

Abe Voelker
fonte
41
Batota ao responder a perguntas do Windows, Cygwin é considerado :-)
mivk
14
Ele estipulou que os usuários do ResourceKit, TimeMem, ptime.exe, PowerShell e outros utilitários começaram a trapacear primeiro. Portanto, o autor tornou seu comentário inadequado antes de você o escrever.
Val
Eu também voto isso desde que achei a solução mais fácil, pois o programa grátis Cmder inclui bash! cmder.net Lembre-se de que se precisar escapar de espaços no bash, use uma barra preta \ imediatamente antes do espaço, em vez de "aspas". por exemplo, cd / c / Program \ Files /
lukescammell
24

Não é tão elegante quanto algumas das funcionalidades do Unix, mas cria um arquivo cmd que se parece com:

@echo off
time < nul
yourexecutable.exe > c:\temp\output.txt
time < nul
rem on newer windows system you can try time /T

Isso exibirá os horários de início e término da seguinte forma:

The current time is: 10:31:57.92
Enter the new time:
The current time is: 10:32:05.94
Enter the new time:
JohnW
fonte
2
Supondo que você não precise de portabilidade entre idiomas diferentes, você também pode colocar um findstr "current" ou algo assim depois do "time <nul" (bom uso de nul por sinal; eu sempre usei echo. | Time, mas isso não parece tão elegante :)). E use "for" para extrair apenas o tempo, não o texto.
214 Joey
2
Se as extensões de comando estiverem ativadas (ou seja, o padrão), a versão do Win XP timepossui uma /topção que apenas exibe a hora atual do sistema, sem solicitar que você insira uma nova hora. No entanto, quando você faz isso, ele exibe apenas horas e minutos, o que pode não ser bom o suficiente para alguns usos. (Resposta See de John Snow a esta pergunta.)
martineau
3
time /Té utilizável apenas se o processo for executado por vários minutos! time < nulé mais feio, mas mais preciso.
## phiLho #
6
Você também pode usar echo %time%que fornece o mesmo formato e precisão como time < nul, mas você evitar a Enter the new time:saída ...
aschipfl
para o uso do tempo locale-independente amd mais precisowmic os get LocalDateTime
phuclv
19

Eu uso o freeware chamado "GS Timer".

Basta criar um arquivo em lotes como este:

timer
yourapp.exe
timer /s

Se você precisar de um conjunto de horários, basta canalizar a saída do timer / s em um arquivo .txt.

Você pode obtê-lo aqui: Utilitários gratuitos para Gammadyne


A resolução é de 0,1 segundos.

pepoluan
fonte
4
Eu não acho que o uso de um aplicativo de terceiros possa ser considerado "feito com meios padrão".
martineau
4
O questionador quis dizer "sem instalar software adicional", mas a resposta superior (aceita) também requer a instalação de um Windows 2003 Resource Kit inteiro! Enfim, timer.exe foi perfeito para o que eu estava procurando, obrigado!
2727 Hugo
1
Este é um link plantado. SoftPedia é um farm de cliques.
Tom A
@ Tom, por favor, explique: o que você quer dizer com "link plantado"?
pepoluan
10
Aqui está um link direto para sua página do desenvolvedor: gammadyne.com/cmdline.htm#timer
Hugo
14

Estou usando o Windows XP e, por algum motivo, o timeit.exe não funciona para mim. Encontrei outra alternativa - PTIME. Isso funciona muito bem.

http://www.pc-tools.net/win32/ptime/

Exemplo -

C:\> ptime

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <[email protected]>

Syntax: ptime command [arguments ...]

ptime will run the specified command and measure the execution time
(run time) in seconds, accurate to 5 millisecond or better. It is an
automatic process timer, or program timer.


C:\> ptime cd

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <[email protected]>

===  cd ===
C:\

Execution time: 0.015 s
Murali Krishnan
fonte
Funciona bem no Windows 8.1 também. Renomeei o meu para timer.exe, porque nunca consigo me lembrar do nome ptime.
Brian Burns
11

Há também o TimeMem (março de 2012):

Este é um utilitário do Windows que executa um programa e exibe seu tempo de execução, uso de memória e estatísticas de E / S. É semelhante em funcionalidade ao utilitário de tempo Unix.

Martin Moene
fonte
10

Contanto que não dure mais de 24 horas ...

@echo off

set starttime=%TIME%
set startcsec=%STARTTIME:~9,2%
set startsecs=%STARTTIME:~6,2%
set startmins=%STARTTIME:~3,2%
set starthour=%STARTTIME:~0,2%
set /a starttime=(%starthour%*60*60*100)+(%startmins%*60*100)+(%startsecs%*100)+(%startcsec%)

:TimeThis
ping localhost 

set endtime=%time%
set endcsec=%endTIME:~9,2%
set endsecs=%endTIME:~6,2%
set endmins=%endTIME:~3,2%
set endhour=%endTIME:~0,2%
if %endhour% LSS %starthour% set /a endhour+=24
set /a endtime=(%endhour%*60*60*100)+(%endmins%*60*100)+(%endsecs%*100)+(%endcsec%)

set /a timetaken= ( %endtime% - %starttime% )
set /a timetakens= %timetaken% / 100
set timetaken=%timetakens%.%timetaken:~-2%

echo.
echo Took: %timetaken% sec.
driblio
fonte
5
Impressionante, mas não acho que funcione se houver 08 ou 09 no horário de início ou de término, porque eles são interpretados como octais. Minha resposta alças que :)
Luke Sampson
6

Aqui está um

Versão do timer Postfix:

Exemplo de uso:

timeout 1 | TimeIt.cmd

Execution took  ~969 milliseconds.

Copie e cole isso em algum editor como, por exemplo, o Notepad ++ e salve-o como TimeIt.cmd :

:: --- TimeIt.cmd ----
    @echo off
    setlocal enabledelayedexpansion

    call :ShowHelp

    :: Set pipeline initialization time
    set t1=%time%

    :: Wait for stdin
    more

    :: Set time at which stdin was ready
    set t2=!time!


    :: Calculate difference
    Call :GetMSeconds Tms1 t1
    Call :GetMSeconds Tms2 t2

    set /a deltaMSecs=%Tms2%-%Tms1%
    echo Execution took ~ %deltaMSecs% milliseconds.

    endlocal
goto :eof

:GetMSeconds
    Call :Parse        TimeAsArgs %2
    Call :CalcMSeconds %1 %TimeAsArgs%

goto :eof

:CalcMSeconds
    set /a %1= (%2 * 3600*1000) + (%3 * 60*1000) + (%4 * 1000) + (%5)
goto :eof

:Parse

    :: Mask time like " 0:23:29,12"
    set %1=!%2: 0=0!

    :: Replace time separators with " "
    set %1=!%1::= !
    set %1=!%1:.= !
    set %1=!%1:,= !

    :: Delete leading zero - so it'll not parsed as octal later
    set %1=!%1: 0= !
goto :eof

:ShowHelp
    echo %~n0 V1.0 [Dez 2015]
    echo.
    echo Usage: ^<Command^> ^| %~nx0
    echo.
    echo Wait for pipe getting ready... :)
    echo  (Press Ctrl+Z ^<Enter^> to Cancel)
goto :eof

^ - Baseado na versão 'Daniel Sparks'

Nadu
fonte
5

Uma alternativa para medir o tempo é simplesmente "Get-Date". Você não tem esse problema com o encaminhamento de saída e assim por diante.

$start = Get-Date
[System.Threading.Thread]::Sleep(1500)
$(Get-Date) - $start

Resultado:

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 506
Ticks             : 15060003
TotalDays         : 1.74305590277778E-05
TotalHours        : 0.000418333416666667
TotalMinutes      : 0.025100005
TotalSeconds      : 1.5060003
TotalMilliseconds : 1506.0003
Rainer
fonte
Isso foi perfeito para mim
Brett Rowberry
4

Este é um one-liner que evita a expansão atrasada , o que pode perturbar certos comandos:

cmd /E /C "prompt $T$$ & echo.%TIME%$ & COMMAND_TO_MEASURE & for %Z in (.) do rem/ "

A saída é algo como:

14:30:27.58$
...
14:32:43.17$ rem/ 

Para longo prazo testes substituir $Tpor $D, $Te %TIME%por %DATE%, %TIME%incluir a data.

Para usar isso dentro de um arquivo em lotes , substitua %Zpor %%Z.


Atualizar

Aqui está um one-liner aprimorado (sem expansão tardia também):

cmd /E /C "prompt $D, $T$$ & (for %# in (.) do rem/ ) & COMMAND_TO_MEASURE & for %# in (.) do prompt"

A saída é semelhante a esta:

2015/09/01, 14:30:27.58$ rem/ 
...
2015/09/01, 14:32:43.17$ prompt

Essa abordagem não inclui o processo de instanciar uma nova cmdno resultado, nem o prompt(s) comando (s).

aschipfl
fonte
4

Dependendo da versão do Windows que você está usando, apenas a execução basho colocará no modo Bash. Isso permitirá que você use vários comandos que não estão disponíveis diretamente no PowerShell (como o timecomando). Cronometrar seu comando agora é tão fácil quanto executar:

# The clause <your-command> (without the angle brackets) denotes the command you want to run.
$ time <your-command>

Nota: Você pode sair facilmente do modo Bash e retornar ao seu shell principal executando exitenquanto estiver no modo Bash.

Isso funcionou perfeitamente para mim (Windows 10) depois de experimentar outros métodos (como Measure-Command) que às vezes produzem estatísticas indesejadas. Espero que isso funcione para você também.

Saddam M
fonte
2
No Windows 10 1607, a melhor resposta.
CarpeDiemKopi
2

Caso alguém mais tenha procurado uma resposta para essa pergunta, existe uma função da API do Windows chamada GetProcessTimes(). Não parece muito trabalho escrever um pequeno programa C que inicie o comando, faça essa chamada e retorne os tempos do processo.

Jeff Pratt
fonte
3
Não parece muito trabalhoso baixar um pequeno programa C que inicie o comando, faça essa chamada (e faça muito mais medições avançadas) e retorne os tempos do processo.
Elazar Leibovich
@ElazarLeibovich powershell? Você pode chamá-lo de c #.
KeyWeeUsr
@KeyWeeUsr você pode usar o Windows API IIRC do PS blogs.technet.microsoft.com/heyscriptingguy/2013/06/25/...
Elazar Leibovich
2

Este é um comentário / edição para agradável de Luke Sampson timecmd.bate resposta para

Por alguma razão, isso só me dá saída em segundos inteiros ... o que para mim é inútil. Quero dizer que executo a pausa do timecmd, e isso sempre resulta em 1,00 s, 2,00 s, 4,00 s ... até 0,00 s! Windows 7. - Camilo Martin, 25 de setembro de 2013 às 16:00 "

Em algumas configurações, os delimitadores podem diferir. A seguinte mudança deve abranger os países da maioria dos países ocidentais.

set options="tokens=1-4 delims=:,." (added comma)

Os %time%milissegundos funcionam no meu sistema depois de adicionar ','

(* porque o site não permite nenhum comentário e não mantém um bom controle de identidade, embora eu sempre use o mesmo email de convidado que combinado com o ipv6 ip e a impressão digital do navegador seja suficiente para identificar exclusivamente sem senha)

Covarde anônimo
fonte
Eu comentei exatamente isso antes de rolar para a sua resposta. De qualquer forma, o script de Luke poderia zerar horas, minutos e segundos, não apenas os subsegundos (que são centésimos de segundo e não milissegundos). Veja aqui: en.wiktionary.org/wiki/centisecond
Tomasz Gandor
2

Aqui está o meu método, sem conversão e sem ms. É útil determinar as durações de codificação (embora limitadas a 24 horas):

@echo off

:start
REM Start time storage
set ST=%time%
echo Process started at %ST%
echo.
echo.

REM Your commands
REM Your commands
REM Your commands

:end
REM Start Time Definition
for /f "tokens=1-3 delims=:" %%a in ("%ST%") do set /a h1=%%a & set /a m1=%%b & set /a s1=%%c

REM End Time Definition
for /f "tokens=1-3 delims=:" %%a in ("%TIME%") do set /a h2=%%a & set /a m2=%%b & set /a s2=%%c

REM Difference
set /a h3=%h2%-%h1% & set /a m3=%m2%-%m1% & set /a s3=%s2%-%s1%

REM Time Adjustment
if %h3% LSS 0 set /a h3=%h3%+24
if %m3% LSS 0 set /a m3=%m3%+60 & set /a h3=%h3%-1
if %s3% LSS 0 set /a s3=%s3%+60 & set /a m3=%m3%-1

echo Start    :    %ST%
echo End    :    %time%
echo.
echo Total    :    %h3%:%m3%:%s3%
echo.
pause
ilko
fonte
1
@echo off & setlocal

set start=%time%

REM Do stuff to be timed here.
REM Alternatively, uncomment the line below to be able to
REM pass in the command to be timed when running this script.
REM cmd /c %*

set end=%time%

REM Calculate time taken in seconds, to the hundredth of a second.
REM Assumes start time and end time will be on the same day.

set options="tokens=1-4 delims=:."

for /f %options% %%a in ("%start%") do (
    set /a start_s="(100%%a %% 100)*3600 + (100%%b %% 100)*60 + (100%%c %% 100)"
    set /a start_hs=100%%d %% 100
)

for /f %options% %%a in ("%end%") do (
    set /a end_s="(100%%a %% 100)*3600 + (100%%b %% 100)*60 + (100%%c %% 100)"
    set /a end_hs=100%%d %% 100
)

set /a s=%end_s%-%start_s%
set /a hs=%end_hs%-%start_hs%

if %hs% lss 0 (
    set /a s=%s%-1
    set /a hs=100%hs%
)
if 1%hs% lss 100 set hs=0%hs%

echo.
echo  Time taken: %s%.%hs% secs
echo.
MikeM
fonte
Não funciona. Obtenção: Parêntese desequilibrado. Parênteses desequilibrados. Operando ausente.
Richard Sandoz
@RichardSandoz Funciona bem, não há parênteses desequilibrado. Como você está usando isso?
MikeM
1

O script a seguir usa apenas "cmd.exe" e gera o número de milissegundos desde o momento em que um pipeline é criado até o momento em que o processo anterior ao script termina. ou seja, digite seu comando e direcione para o script. Exemplo: "timeout 3 | runtime.cmd" deve render algo como "2990". Se você precisar da saída do tempo de execução e da saída stdin, redirecione o stdin antes do pipe - ex: "dir / s 1> temp.txt | runtime.cmd" despejaria a saída do comando "dir" para "temp.txt" e imprimiria o tempo de execução no console.

:: --- runtime.cmd ----
@echo off
setlocal enabledelayedexpansion

:: find target for recursive calls
if not "%1"=="" (
    shift /1
    goto :%1
    exit /b
)

:: set pipeline initialization time
set t1=%time%

:: wait for stdin
more > nul

:: set time at which stdin was ready
set t2=!time!

::parse t1
set t1=!t1::= !
set t1=!t1:.= !
set t1=!t1: 0= !

:: parse t2
set t2=!t2::= !
set t2=!t2:.= !
set t2=!t2: 0= !

:: calc difference
pushd %~dp0
for /f %%i in ('%0 calc !t1!') do for /f %%j in ('%0 calc !t2!') do (
    set /a t=%%j-%%i
    echo !t!
)
popd
exit /b
goto :eof

:calc
set /a t=(%1*(3600*1000))+(%2*(60*1000))+(%3*1000)+(%4)
echo !t!
goto :eof

endlocal
Daniel Sparks
fonte
Bem, em vez de chamar o script recursivamente , considere fazê-lo assim call :calc. Eu fiz isso aqui. O Code get é um pouco melhor assim. : D
Nadu
Bug # 1 Falha na 12ª hora. Exemplo: " 0 : 23: 19,42" Bug # 2 Falha se o ponto decimal for outra coisa que não. mesmo exemplo: "0:23:19 , 42" aqui o ponto decimal é, <__________> Tentou editar, no entanto, que idiota idiota na 'comissão de aprovação de edição' o rejeitou - 3 de 5 votaram "Esta edição também muda grande parte da intenção original dos autores ". por isso, se você quiser editar a sua sorte ou apenas manter os erros, para que a "intenção original do autor permaneça intacta". Facepalm
Nadu
Não é possível produzir milissegundos quando a resolução do seu relógio mal consegue 1/100 de segundo de resolução.
precisa saber é o seguinte
1

A resposta de driblio pode ser um pouco mais curta (embora não seja muito legível)

@echo off

:: Calculate the start timestamp
set _time=%time%
set /a _hours=100%_time:~0,2%%%100,_min=100%_time:~3,2%%%100,_sec=100%_time:~6,2%%%100,_cs=%_time:~9,2%
set /a _started=_hours*60*60*100+_min*60*100+_sec*100+_cs


:: yourCommandHere


:: Calculate the difference in cSeconds
set _time=%time%
set /a _hours=100%_time:~0,2%%%100,_min=100%_time:~3,2%%%100,_sec=100%_time:~6,2%%%100,_cs=%_time:~9,2%
set /a _duration=_hours*60*60*100+_min*60*100+_sec*100+_cs-_started

:: Populate variables for rendering (100+ needed for padding)
set /a _hours=_duration/60/60/100,_min=100+_duration/60/100%%60,_sec=100+(_duration/100%%60%%60),_cs=100+_duration%%100

echo Done at: %_time% took : %_hours%:%_min:~-2%:%_sec:~-2%.%_cs:~-2%

::prints something like:
::Done at: 12:37:53,70 took: 0:02:03.55

Para a observação de Luke Sampson, esta versão é octal segura, embora a tarefa deva ser concluída em 24 horas.

Alexander
fonte
Não funciona. Operador ausente quando a hora de um dígito.
Richard Sandoz
set _time=%time: =0%corrige o problema da hora de um dígito - substitua nos dois lugares.
Laur
1
  1. No diretório em que está o seu programa, digite notepad mytimer.bat, clique em 'yes' para criar um novo arquivo.

  2. Cole o código abaixo, substituindo YourApp.exepelo seu programa, e salve.

    @echo off
    date /t
    time /t
    YourApp.exe
    date /t
    time /t
  3. Digite mytimer.batna linha de comando e pressione Enter.

Peter Mortensen
fonte
7
time / t apenas fornece tempo em HH: MM. Para cronometrar um executável, você geralmente precisa de mais precisão ... É algo que você possa configurar para reduzir a frações de segundo? Eu testei o sollution de johnw (time <nul), e que realmente dá o tempo para baixo a 1 / 100s: hh: mm: SS.XX
temor
1

meu código fornece o tempo de execução em milissegundos, até 24 horas, é insensível à localidade e responde por valores negativos se o código for executado até meia-noite. ele usa expansão atrasada e deve ser salvo em um arquivo cmd / bat.

antes do seu código:

SETLOCAL EnableDelayedExpansion

for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set t=%%I
set /a t1 = %t:~8,1%*36000 + %t:~9,1%*3600 + %t:~10,1%*600 + %t:~11,1%*60 + %t:~12,1%*10 + %t:~13,1% && set t1=!t1!%t:~15,3%

após o seu código:

for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set t=%%I
set /a t2 = %t:~8,1%*36000 + %t:~9,1%*3600 + %t:~10,1%*600 + %t:~11,1%*60 + %t:~12,1%*10 + %t:~13,1% && set t2=!t2!%t:~15,3%
set /a t2-=t1 && if !t2! lss 0 set /a t2+=24*3600000

se você deseja tempo de execução no formato HH: mm: ss.000, adicione:

set /a "h=t2/3600000,t2%%=3600000,m=t2/60000,t2%%=60000" && set t2=00000!t2!&& set t2=!t2:~-5!
if %h% leq 9 (set h=0%h%) && if %m% leq 9 (set m=0%m%)
set t2=%h%:%m%:%t2:~0,2%.%t2:~2,3%

ENDLOCAL

variável t2mantém seu tempo de execução, você pode echo %t2%exibi-lo.

robotik
fonte
1

Tendo o Perl instalado a solução de contratações disponível, execute:

C:\BATCH>time.pl "echo Fine result"
0.01063
Fine result

STDERR vem antes dos segundos medidos

#!/usr/bin/perl -w

use Time::HiRes qw();
my $T0 = [ Time::HiRes::gettimeofday ];

my $stdout = `@ARGV`;

my $time_elapsed = Time::HiRes::tv_interval( $T0 );

print $time_elapsed, "\n";
print $stdout;
Victor Mironov
fonte
0

Usando um sub para retornar o tempo em centésimos de segundo

::tiemeit.cmd
@echo off
Setlocal EnableDelayedExpansion

call :clock 

::call your_command  or more > null to pipe this batch after your_command

call :clock

echo %timed%
pause
goto:eof

:clock
if not defined timed set timed=0
for /F "tokens=1-4 delims=:.," %%a in ("%time%") do ( 
set /A timed = "(((1%%a - 100) * 60 + (1%%b - 100)) * 60 + (1%%c - 100))  * 100 + (1%%d - 100)- %timed%"
)
goto:eof
Antoni Gual Via
fonte
0

TIMER "Lean and Mean" com formato Regional, 24h e suporte a entrada mista
Adaptando o corpo do método de substituição de Aacini , sem IFs, apenas um FOR (minha correção regional)

1: Arquivo timer.bat colocado em algum lugar no% PATH% ou no diretório atual

@echo off & rem :AveYo: compact timer function with Regional format, 24-hours and mixed input support
if not defined timer_set (if not "%~1"=="" (call set "timer_set=%~1") else set "timer_set=%TIME: =0%") & goto :eof
(if not "%~1"=="" (call set "timer_end=%~1") else set "timer_end=%TIME: =0%") & setlocal EnableDelayedExpansion
for /f "tokens=1-6 delims=0123456789" %%i in ("%timer_end%%timer_set%") do (set CE=%%i&set DE=%%k&set CS=%%l&set DS=%%n)
set "TE=!timer_end:%DE%=%%100)*100+1!"     & set "TS=!timer_set:%DS%=%%100)*100+1!"
set/A "T=((((10!TE:%CE%=%%100)*60+1!%%100)-((((10!TS:%CS%=%%100)*60+1!%%100)" & set/A "T=!T:-=8640000-!"
set/A "cc=T%%100+100,T/=100,ss=T%%60+100,T/=60,mm=T%%60+100,hh=T/60+100"
set "value=!hh:~1!%CE%!mm:~1!%CE%!ss:~1!%DE%!cc:~1!" & if "%~2"=="" echo/!value!
endlocal & set "timer_end=%value%" & set "timer_set=" & goto :eof

Uso:
temporizador & echo start_cmds & tempo limite / t 3 & echo end_cmds & temporizador
temporizador e temporizador "23: 23: 23,00"
temporizador "23: 23: 23,00" & temporizador
temporizador "13.23.23,00" e temporizador "03: 03: 03.00"
timer e timer "0: 00: 00.00" no & cmd / v: on / c eco até meia-noite =! Timer_end!
A entrada agora pode ser mista, para aqueles improváveis, mas possíveis alterações no formato de hora durante a execução

2: Função : timer incluído no script em lote (uso de exemplo abaixo):

@echo off
set "TIMER=call :timer" & rem short macro
echo.
echo EXAMPLE:
call :timer
timeout /t 3 >nul & rem Any process here..
call :timer
echo.
echo SHORT MACRO:
%TIMER% & timeout /t 1 & %TIMER% 
echo.
echo TEST INPUT:
set "start=22:04:04.58"
set "end=04.22.44,22"
echo %start% ~ start & echo %end% ~ end
call :timer "%start%"
call :timer "%end%"
echo.
%TIMER% & %TIMER% "00:00:00.00" no 
echo UNTIL MIDNIGHT: %timer_end%
echo.
pause 
exit /b

:: para testá-lo, copie e cole as seções de código acima e abaixo

rem :AveYo: compact timer function with Regional format, 24-hours and mixed input support 
:timer Usage " call :timer [input - optional] [no - optional]" :i Result printed on second call, saved to timer_end 
if not defined timer_set (if not "%~1"=="" (call set "timer_set=%~1") else set "timer_set=%TIME: =0%") & goto :eof
(if not "%~1"=="" (call set "timer_end=%~1") else set "timer_end=%TIME: =0%") & setlocal EnableDelayedExpansion
for /f "tokens=1-6 delims=0123456789" %%i in ("%timer_end%%timer_set%") do (set CE=%%i&set DE=%%k&set CS=%%l&set DS=%%n)
set "TE=!timer_end:%DE%=%%100)*100+1!"     & set "TS=!timer_set:%DS%=%%100)*100+1!"
set/A "T=((((10!TE:%CE%=%%100)*60+1!%%100)-((((10!TS:%CS%=%%100)*60+1!%%100)" & set/A "T=!T:-=8640000-!"
set/A "cc=T%%100+100,T/=100,ss=T%%60+100,T/=60,mm=T%%60+100,hh=T/60+100"
set "value=!hh:~1!%CE%!mm:~1!%CE%!ss:~1!%DE%!cc:~1!" & if "%~2"=="" echo/!value!
endlocal & set "timer_end=%value%" & set "timer_set=" & goto :eof

CE, DE e CS, DS representam final de dois pontos, final de ponto e conjunto de dois pontos, conjunto de pontos - usado para suporte a formatos mistos

AveYo
fonte
0

O script a seguir emula o tempo da época * nix, mas é local e regional. Ele deve lidar com casos de borda de calendário, incluindo anos bissextos. Se o Cygwin estiver disponível, os valores da época poderão ser comparados especificando a opção Cygwin .

Estou no EST e a diferença relatada é de 4 horas, o que é relativamente correto. Existem algumas soluções interessantes para remover as dependências regionais e TZ, mas nada trivial que eu notei.

@ECHO off
SETLOCAL EnableDelayedExpansion

::
::  Emulates local epoch seconds
::

:: Call passing local date and time
CALL :SECONDS "%DATE%" "%TIME%"
IF !SECONDS! LEQ 0 GOTO END

:: Not testing - print and exit
IF NOT "%~1"=="cygwin" (
    ECHO !SECONDS!
    GOTO END
)

:: Call on Cygwin to get epoch time
FOR /F %%c IN ('C:\cygwin\bin\date +%%s') DO SET EPOCH=%%c

:: Show the results
ECHO Local Seconds: !SECONDS!
ECHO Epoch Seconds: !EPOCH!

:: Calculate difference between script and Cygwin
SET /A HOURS=(!EPOCH!-!SECONDS!)/3600
SET /A FRAC=(!EPOCH!-!SECONDS!)%%3600

:: Delta hours shown reflect TZ
ECHO Delta Hours: !HOURS! Remainder: !FRAC!

GOTO END

:SECONDS
SETLOCAL  EnableDelayedExpansion

    :: Expecting values from caller
    SET DATE=%~1
    SET TIME=%~2

    :: Emulate Unix epoch time without considering TZ
    SET "SINCE_YEAR=1970"

    :: Regional constraint! Expecting date and time in the following formats:
    ::   Sun 03/08/2015   Day MM/DD/YYYY
    ::   20:04:53.64         HH:MM:SS
    SET VALID_DATE=0
    ECHO !DATE! | FINDSTR /R /C:"^... [0-9 ][0-9]/[0-9 ][0-9]/[0-9][0-9][0-9][0-9]" > nul && SET VALID_DATE=1
    SET VALID_TIME=0
    ECHO !TIME! | FINDSTR /R /C:"^[0-9 ][0-9]:[0-9 ][0-9]:[0-9 ][0-9]" > nul && SET VALID_TIME=1
    IF NOT "!VALID_DATE!!VALID_TIME!"=="11" (
        IF !VALID_DATE! EQU 0  ECHO Unsupported Date value: !DATE! 1>&2
        IF !VALID_TIME! EQU 0  ECHO Unsupported Time value: !TIME! 1>&2
        SET SECONDS=0
        GOTO SECONDS_END
    )

    :: Parse values
    SET "YYYY=!DATE:~10,4!"
    SET "MM=!DATE:~4,2!"
    SET "DD=!DATE:~7,2!"
    SET "HH=!TIME:~0,2!"
    SET "NN=!TIME:~3,2!"
    SET "SS=!TIME:~6,2!"
    SET /A YEARS=!YYYY!-!SINCE_YEAR!
    SET /A DAYS=!YEARS!*365

    :: Bump year if after February  - want leading zeroes for this test
    IF "!MM!!DD!" GEQ "0301" SET /A YEARS+=1

    :: Remove leading zeros that can cause octet probs for SET /A
    FOR %%r IN (MM,DD,HH,NN,SS) DO (
        SET "v=%%r"
        SET "t=!%%r!"
        SET /A N=!t:~0,1!0
        IF 0 EQU !N! SET "!v!=!t:~1!"
    )

    :: Increase days according to number of leap years
    SET /A DAYS+=(!YEARS!+3)/4-(!SINCE_YEAR!%%4+3)/4

    :: Increase days by preceding months of current year
    FOR %%n IN (31:1,28:2,31:3,30:4,31:5,30:6,31:7,31:8,30:9,31:10,30:11) DO (
        SET "n=%%n"
        IF !MM! GTR !n:~3! SET /A DAYS+=!n:~0,2!
    )

    :: Multiply and add it all together
    SET /A SECONDS=(!DAYS!+!DD!-1)*86400+!HH!*3600+!NN!*60+!SS!

:SECONDS_END
ENDLOCAL & SET "SECONDS=%SECONDS%"
GOTO :EOF

:END
ENDLOCAL
bvj
fonte
Curioso sobre o voto negativo. Obrigado.
BVJ
0

Uma solução usando PHP puro para cmd e um env. variável:

@echo off
setlocal enableextensions

REM set start time env var
FOR /F "tokens=* USEBACKQ" %%F IN (`php -r "echo microtime(true);"`) DO ( SET start_time=%%F )

## PUT_HERE_THE_COMMAND_TO_RUN ##

REM echo elapsed time
php -r "echo 'elapsed: ' . (round(microtime(true) - trim(getenv('start_time')), 2)) . ' seconds' . mb_convert_encoding('&#13;&#10;', 'UTF-8', 'HTML-ENTITIES');"
  • não há necessidade de cygwin ou utilitários não confiáveis. Útil quando o PHP está disponível localmente

  • precisão e formato de saída podem ser facilmente ajustados

  • a mesma ideia pode ser portada para o PowerShell

mvorisek
fonte