如何在 Windows 命令行上测量命令的执行时间?

Posted

技术标签:

【中文标题】如何在 Windows 命令行上测量命令的执行时间?【英文标题】:How do I measure execution time of a command on the Windows command line? 【发布时间】:2010-10-14 23:36:15 【问题描述】:

是否有一种内置方法可以测量 Windows 命令行上命令的执行时间?

【问题讨论】:

【参考方案1】:

PowerShell 有一个名为 Measure-Command 的 cmdlet。您必须确保 PowerShell 在运行它的机器上可用。

PS> Measure-Command  echo hi 

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

Measure-Command 捕获命令的输出。您可以使用Out-Default 将输出重定向回您的控制台:

PS> Measure-Command  echo hi | Out-Default 
hi

Days              : 0
...

正如Makotoe 评论的那样,Measure-Command 返回一个TimeSpan 对象,因此测量的时间被打印为一堆字段。您可以使用ToString() 将对象格式化为时间戳字符串:

PS> (Measure-Command  echo hi | Out-Default ).ToString()
hi
00:00:00.0001318

如果Measure-Command 中的命令更改了控制台文本颜色,请使用[Console]::ResetColor() 将其重置为正常。

【讨论】:

这是 Windows 7 用户的最佳解决方案,因为 timeit.exe 似乎不支持 Windows 7 如果你想使用内部的dos命令(例如:dir、echo、del等)不要忘记插入“cmd /c”:Measure-Command cmd /c dir /sc:\windows > nul 如果您在当前目录中对.exe 进行基准测试,请使用:Measure-Command .\your.exe 。 PowerShell 显然不会从 pwd 运行东西,除非明确告知。 令人讨厌的是它隐藏了标准输出。 这是根本不是一个工具'类似于Bash的时间命令'。很高兴知道...但是:它不执行 并返回到 <stdout> 括在大括号中的命令的结果!【参考方案2】:

如果你愿意

    以(hh:mm:ss.ff 格式)测量执行时间精确到百分之一秒 不必下载和安装资源包 看起来像一个巨大的 DOS 书呆子(谁没有)

尝试将以下脚本复制到新的批处理文件中(例如 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)

用法

如果您将 timecmd.bat 放在路径中的目录中,您可以从任何地方调用它,如下所示:

timecmd [your command]

例如

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

如果要进行输出重定向,可以这样引用命令:

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

这应该处理从午夜之前到午夜之后运行的命令,但是如果您的命令运行 24 小时或更长时间,输出将是错误的。

【讨论】:

%* 替换 cmd /c %* 有效,除非您的命令是另一个批处理文件。然后你必须做 timecmd call other.bat 出于某种原因,这只能在整秒内给我输出......这对我来说毫无用处。我的意思是我运行timecmd pause,它总是导致 1.00 秒、2.00 秒、4.00 秒……甚至 0.00 秒!视窗 7。 @CamiloMartin 和其他拥有此功能的人(如我) - 您可能有一个语言环境,它使用逗号而不是 DOT 来表示十进制。因此,在此脚本中,将 delims=:. 更改为 delims=:.,,然后它应该“全面”工作。 该脚本中有一个严重的算术错误:尝试一下:set start=10:10:10.10set end=10:11:10.09 它会输出:command took 0:1:-1.99 (59.99s total) 您应该颠倒执行“lss 0”的 4 行的顺序" 比较,以便进位正确地从低位到高位六十进制数字进行。那么输出变为:command took 0:0:59.99 (59.99s total) 对于任何想知道的人:TomaszGandor 和 Jean-FrançoisLarvoire 的修复已被编辑到上面的脚本中。另外@Jashan:您的毫秒填充中有一个错误的错误(实际上是百分之一,并且您使用的是secs var而不是ms),所以它应该是:set "ms=0%ms%"set "ms=%ms:~-2%"。但除此之外,我喜欢这个!【参考方案3】:

呵呵,最简单的解决办法可能是这样的:

echo %time%
YourApp.exe
echo %time%

这适用于所有开箱即用的 Windows。


如果应用程序使用控制台输出,将开始时间存储在临时变量中可能会很方便:

set startTime=%time%
YourApp.exe
echo Start Time: %startTime%
echo Finish Time: %time%

【讨论】:

你疯了吗?!这涉及在你的大脑中进行数学运算。这就是我们发明计算机的原因,所以我们可以避免做类似的事情。 太棒了!即使,对于 CPU 时间,它并没有真正的帮助 更好(如果您的应用向控制台输出输出):set startTime=%time% \n YourApp.exe \n echo Start Time: %startTime% \n echo Finish Time: %time%(抱歉,无法在评论中获得换行符) @LukeSampson,您可以使用set 来计算。 ;-)哦等等,没关系,你已经在下面做了。 不,这是一个糟糕的选择。这告诉你挂钟时间,而不是 CPU 时间。因此,即使您的命令行可能只需要 100 毫秒,如果有另一个应用程序占用 CPU,您的应用程序可能需要几秒钟(减少 100 倍或更多)。事实上,如果您的机器正在抖动,您甚至可以等待一分钟让您的小 100 毫秒应用程序运行。跟踪 CPU 时间,而不是挂钟时间!【参考方案4】:

只是对the answer from Casey.K 的一点扩展,关于使用来自PowerShell 的Measure-Command

    您可以从标准命令提示符调用 PowerShell,如下所示:

    powershell -Command "Measure-Command echo hi"
    

    这会吃掉标准输出,但您可以通过在 PowerShell 中像这样添加 | Out-Default 来防止这种情况发生:

    Measure-Command echo hi | Out-Default
    

    或者从命令提示符:

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

当然,您可以随意将其封装在脚本文件 *.ps1*.bat

【讨论】:

如果我们要测量的命令有引号怎么办?在这种情况下可以将其转换为 .bat 脚本吗?例如measureTime.bat "c:\program files\some dir\program.exe"【参考方案5】:

如果您使用的是 Windows 2003(请注意,不支持 Windows Server 2008 及更高版本),您可以使用 Windows Server 2003 资源工具包,其中包含显示详细执行统计信息的 timeit.exe。下面是一个例子,给命令“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

您可以在 Windows 2003 Resource Kit 中获得 TimeIt。无法从 Microsoft 下载中心直接下载,但仍可以从 archive.org - Windows Server 2003 Resource Kit Tools 获取。

【讨论】:

此套件在 windows 2008 64bit 上存在问题,不适用于 2008 R2 有什么方法可以测量内核时间和/或衍生子进程使用的时间? 仅供参考 - 我认为 timeit 不适用于 Windows 7 64 位。您收到错误“无法查询系统性能数据 (c0000004)。相反,请使用 PowerShell 的“Measure-Command”,如 Casey.K 建议的:***.com/questions/673523/… 在 Windows 7 中我看到“'timeit' 未被识别为内部或外部命令、可运行程序或批处理文件。” 我在 Windows 10 中看不到该命令,也找不到适用于 Win 10 的资源工具包。有谁知道如何在 10 中获得这个?【参考方案6】:

我在 Windows Server 2008 R2 中使用的单行代码是:

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

只要 mycommand 不需要引号(这与 cmd 的引号处理有关)。 /v:on 允许独立评估两个不同的 TIME 值,而不是在执行命令时计算一次。

【讨论】:

这也不适用于“垃圾邮件”批次,它会覆盖第一次标签并暗示您更换计算机进行计算,如***.com/questions/673523/…中所述 通常你可以在cmd中通过^转义引号(比如^" 如果第二次重复 cmd /v:on,我们甚至可以让 mycommand 包含引号。示例:cmd /v:on /c echo !TIME! & echo "Quoted mycommand" & cmd /v:on /c echo !TIME!. 更简单:echo %time% & *mycommand* & call echo %^time%。另请参阅this answer。 如果你的命令输出太多,也许把两个时间放在一起会更容易:cmd /v:on /c "mycommand & echo begin=%time% endtime=!time!"【参考方案7】:

如果您打开了命令窗口并手动调用命令,则可以在每个提示符上显示时间戳,例如

prompt $d $t $_$P$G

它给了你类似的东西:

23.03.2009 15:45:50,77

C:\>

如果您有一个执行命令的小批量脚本,请在每个命令前留一个空行,例如

(空行)

myCommand.exe

(下一个空行)

myCommand2.exe

您可以通过提示符中的时间信息来计算每个命令的执行时间。最好的方法可能是将输出通过管道传输到文本文件以供进一步分析:

MyBatchFile.bat > output.txt

【讨论】:

我想我会在讨论后几年停下来感谢您分享提示命令。我见过很多 CMD 技巧(更像是一个 bash 家伙),但这个没有引起我的注意。 简单,优雅,无需安装,无需为一次性命令编写批处理文件,并且可以对批处理文件中的每一步进行计时。【参考方案8】:

由于其他人建议安装免费软件和 PowerShell 之类的东西,您也可以安装 Cygwin,这样您就可以访问许多基本的 Unix 命令,例如 time:

abe@abe-PC:~$ time sleep 5

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

不确定 Cygwin 增加了多少开销。

【讨论】:

在回答 Windows 问题时,Cygwin 被认为是作弊:-) 他规定ResourceKit、TimeMem、ptime.exe、PowerShell等实用程序用户首先开始作弊。因此,作者在您发表评论之前已将您的评论不当。 我也赞成这个,因为我发现它是最简单的解决方案,因为免费程序 Cmder 包含 bash! cmder.net 请记住,如果您需要在 bash 中转义空格,请在空格前使用黑斜线 \,而不是“引号”。例如,cd /c/Program\ Files/ 我是开发人员并使用 WSL。 %windir%\system32\wsl.exe -cur_console:pm:/mnt 我们有一个 bash 命令行 :-)【参考方案9】:

不像 Unix 上的某些功能那么优雅,但创建一个 cmd 文件,如下所示:

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

这将显示开始和停止时间,如下所示:

The current time is: 10:31:57.92
Enter the new time:
The current time is: 10:32:05.94
Enter the new time:

【讨论】:

假设您不需要跨不同语言的可移植性,您还可以在 "time 如果启用命令扩展(即默认),Win XP 版本的time 有一个/t 选项,它只显示当前系统时间,而不提示您输入新的时间。但是,当您这样做时,它只显示小时和分钟,这对于某些用途可能不够好。 (请参阅 John Snow 对此问题的回答。) time /T 仅在进程运行几分钟时才可用! time &lt; nul 更丑但更精确。 您也可以使用echo %time%,它提供与time &lt; nul 相同的格式和精度,但要避免Enter the new time: 输出... 独立于语言环境和更精确的时间使用wmic os get LocalDateTime【参考方案10】:

我使用名为“GS Timer”的免费软件。

只需像这样制作一个批处理文件:

timer
yourapp.exe
timer /s

如果您需要一组时间,只需将 timer /s 的输出通过管道传输到 .txt 文件中。

您可以在这里获取:Gammadyne's Free DOS Utilities


分辨率为 0.1 秒。

【讨论】:

我不认为可以考虑使用第三方应用程序“使用标准方式”。 提问者的意思是“不安装其他软件”,但最重要的(接受的)答案还需要安装整个 Windows 2003 Resource Kit!无论如何,timer.exe 非常适合我正在寻找的东西,谢谢! 这是一个植入的链接。 SoftPedia 是一个点击农场。 @Tom 请解释一下,“种植链接”是什么意思? 这里是开发者自己页面的直接链接:gammadyne.com/cmdline.htm#timer【参考方案11】:

我使用的是 Windows XP,但由于某种原因 timeit.exe 不适合我。我找到了另一种选择 - PTIME。这很好用。

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

例子-

C:\> ptime

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

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 <jberkes@pc-tools.net>

===  cd ===
C:\

Execution time: 0.015 s

【讨论】:

在 Windows 8.1 上也能很好地工作。我将我的重命名为 timer.exe,因为我永远记不起 ptime 这个名字。【参考方案12】:

只要不超过 24 小时...

@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.

【讨论】:

令人印象深刻,但如果开始或结束时间中有 08 或 09,我认为它不起作用,因为它们被解释为八进制。我的回答处理了:)【参考方案13】:

还有TimeMem(2012 年 3 月):

这是一个 Windows 实用程序,它执行程序并显示其 执行时间、内存使用情况和 IO 统计信息。它是相似的 Unix 时间实用程序的功能。

【讨论】:

【参考方案14】:

这是一个

后缀定时器版本:

使用示例:

超时 1 | TimeIt.cmd

Execution took  ~969 milliseconds.

将其复制并粘贴到某个编辑器中,例如 Notepad++ 并将其保存为 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

^ - 基于'Daniel Sparks' Version

【讨论】:

【参考方案15】:

根据您使用的 Windows 版本,只需运行 bash 即可让您进入 Bash 模式。这将允许您直接使用 PowerShell 上不可用的一堆命令(例如 time 命令)。计时命令现在就像执行一样简单:

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

注意:您可以通过在 Bash 模式下运行 exit 轻松退出 Bash 模式并返回主流 shell。

在尝试了其他有时会产生不良统计数据的方法(如Measure-Command)后,这对我来说非常有效(Windows 10)。希望这也适用于您。

【讨论】:

从 Windows 10 1607 开始是最佳答案。【参考方案16】:

这是避免delayed expansion 的单行代码,这可能会干扰某些命令:

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

输出类似于:

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

对于长期测试,将$T 替换为$D, $T,将%TIME% 替换为%DATE%, %TIME% 以包含日期。

要在批处理文件中使用它,请将%Z 替换为%%Z


更新

这是一个改进的单线(也没有delayed expansion):

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

输出类似于:

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

这种方法不包括在结果中实例化新的cmd 的过程,也不包括prompt 命令。

【讨论】:

【参考方案17】:

测量时间的替代方法是简单地“获取日期”。转发输出等等,你没有那么麻烦。

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

输出:

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

【讨论】:

这对我来说是完美的 Get-Date 命令在 PowerShell 中可以正常工作,不幸的是它在 Windows 10 上的常规命令提示符下没有。【参考方案18】:

这是我的方法,没有转换也没有毫秒。确定编码持续时间很有用(但仅限于 24 小时):

@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

【讨论】:

【参考方案19】:

我的代码以毫秒为单位为您提供运行时间,最长为 24 小时,它对语言环境不敏感,并且如果代码运行到午夜则考虑负值。它使用延迟扩展,应保存在 cmd/bat 文件中。

在您的代码之前:

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%

在您的代码之后:

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

如果您希望运行时间为 HH:mm:ss.000 格式,请添加:

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

变量t2保存你的运行时间,你可以echo %t2%显示它。

【讨论】:

【参考方案20】:

如果其他人来这里寻找这个问题的答案,有一个名为GetProcessTimes() 的 Windows API 函数。编写一个可以启动命令、进行调用并返回处理时间的小 C 程序看起来并不需要太多工作。

【讨论】:

下载一个可以启动命令、进行此调用(以及更多高级测量)并返回处理时间的小 C 程序看起来并不需要太多工作。 @ElazarLeibovich powershell?您可以从 C# 中调用它。 @KeyWeeUsr 你可以使用来自 PS 的 Windows API IIRC blogs.technet.microsoft.com/heyscriptingguy/2013/06/25/…【参考方案21】:

这个是对 Luke Sampson 的 timecmd.bat 的评论/编辑并回复

由于某种原因,这只会在几秒钟内给我输出……这对我来说毫无用处。我的意思是我运行 timecmd pause,它总是导致 1.00 秒、2.00 秒、4.00 秒……甚至 0.00 秒! Windows 7. – Camilo Martin 2013 年 9 月 25 日 16:00"

在某些配置中,分隔符可能不同。以下更改应至少涵盖大多数西方国家。

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

添加“,”后,%time% 毫秒在我的系统上工作

(*因为网站不允许匿名评论并且不能很好地跟踪身份,即使我总是使用相同的访客电子邮件,结合 ipv6 ip 和浏览器指纹应该足以在没有密码的情况下唯一识别)

【讨论】:

我在向下滚动到您的答案之前发表了评论。无论如何,Luke 的脚本可以零填充小时、分钟和秒,而不仅仅是亚秒(这是 厘秒,而不是毫秒,顺便说一句)。见这里:en.wiktionary.org/wiki/centisecond【参考方案22】:
@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.

【讨论】:

不起作用。得到:不平衡的括号。不平衡的括号。缺少操作数。 @RichardSandoz 它工作正常,没有不平衡的括号。你是怎么用的?【参考方案23】:

以下脚本仅使用“cmd.exe”并输出从创建管道到脚本之前的进程退出的毫秒数。即,键入您的命令,然后通过管道传递给脚本。示例:“timeout 3 | runtime.cmd”应该产生类似“2990”的结果。如果您需要运行时输出和标准输入输出,请在管道之前重定向标准输入 - 例如:“dir /s 1>temp.txt | runtime.cmd”会将“dir”命令的输出转储到“temp.txt”并将运行时打印到控制台。

:: --- 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

【讨论】:

好吧,而不是递归调用脚本,考虑像这样call :calc。我在这里做到了。 link 代码得到一些更好的方式。 :D Bug #1 将在第 12 小时失败。示例:" 0:23:19,42" Bug #2 如果小数点不是 .同样的例子:“0:23:19 , 42”这里的小数点是,<__________> 很好地尝试编辑,但是“编辑批准委员会”中的那个愚蠢的****拒绝了它 - 3 5 投票“此编辑更改了作者的原始意图太多。”所以如果你想试试运气编辑或者只是保留错误 - 所以“作者的原始意图保持不变”。 掌心 当您的时钟分辨率勉强能够达到 1/100 秒分辨率时,无法输出毫秒。【参考方案24】:

driblio 的答案可以短一些(虽然可读性不强)

@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

对于 Luke Sampson 的 remark,此版本是八进制安全的,但任务应在 24 小时内完成。

【讨论】:

不起作用。单位小时时缺少运算符。 set _time=%time: =0% 修复了个位数小时问题 - 在两个地方都替换。【参考方案25】:

    在你的程序所在目录中,输入notepad mytimer.bat,点击“是”创建一个新文件。

    粘贴下面的代码,用你的程序替换YourApp.exe,然后保存。

    @echo off
    date /t
    time /t
    YourApp.exe
    date /t
    time /t
    

    在命令行中输入mytimer.bat,然后回车。

【讨论】:

time /t 只为您提供 HH:MM 时间。要为可执行文件计时,您通常需要更高的准确性……您可以设置什么来降低到几分之一秒?我测试了 JohnW 的解决方案(时间 【参考方案26】:

让 Perl 安装了可用的招聘解决方案,运行:

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

STDERR 出现在测量秒数之前

#!/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;

【讨论】:

【参考方案27】:

powershell 的另一种方法:

@echo off
for /f %%t in ('powershell "(get-date).tofiletime()"') do set mst=%%t

rem some commands

powershell ((get-date).tofiletime() - %mst%)

这将以毫秒为单位打印执行时间。

【讨论】:

【参考方案28】:

使用 sub 以百分之一秒为单位返回时间

::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

【讨论】:

【参考方案29】:

具有区域格式、24 小时制和混合输入支持的“精益和平均”计时器 调整Aacini's 替换方法体,没有 IF,只有一个 FOR(我的区域修复)

1:文件 timer.bat 放置在 %PATH% 或当前目录中的某个位置

@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

用法:timer & echo start_cmds & timeout /t 3 & echo end_cmds & timertimer & timer "23:23:23,00"timer "23:23:23,00" & timer定时器“13.23.23,00”和定时器“03:03:03.00”定时器 timer "0:00:00.00" no & cmd /v:on /c echo until深夜=!timer_end!现在可以混合输入,因为那些不太可能但可能的时间格式在执行

2:函数 :timer 与批处理脚本捆绑在一起(示例用法如下):

@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

:: 为了测试它,复制粘贴上面和下面的代码部分

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 和 CS,DS 代表冒号结尾,点结尾和冒号集,点集 - 用于混合格式支持

【讨论】:

【参考方案30】:

以下脚本模拟 *nix 纪元时间,但它是本地和区域的。它应该处理包括闰年在内的日历边缘情况。如果Cygwin 可用,则可以通过指定Cygwin 选项来比较纪元值。

我在美国东部标准时间,报告的差异是 4 小时,这是相对正确的。有一些有趣的解决方案可以消除 TZ 和区域依赖关系,但我没有注意到任何微不足道的问题。

@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

【讨论】:

以上是关于如何在 Windows 命令行上测量命令的执行时间?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 命令行上使用 pg_restore?

如何在 Windows 命令行上获取一组文件的最后修改日期?

Symfony - 进程运行抛出异常 - 在命令行上执行有效

如何防止 qmake 在链接器命令行上添加控制台子系统?

我应该如何使用英特尔的 Windows 编译器在命令行上禁用 C++0x 和/或 C++11?

在 windows 的命令行上创建一个空文件(如 linux touch 命令)