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

648

Windows命令行中是否有内置的方法来测量命令的执行时间?

34个回答

649

PowerShell有一个名为Measure-Command的命令,可以用来进行此操作。您需要确保运行该命令的计算机上安装了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() 来将它重置回正常。


23
对于使用 Windows 7 的用户而言,这是最佳解决方案,因为 timeit.exe 看起来不支持 Windows 7。 - Michael La Voie
16
如果您想使用内部的DOS命令(例如:dir,echo,del等),请不要忘记插入“cmd /c”:测量-命令{ cmd /c dir /s c:\windows > nul } - LietKynes
13
如果你要对当前目录中的 .exe 进行基准测试,请使用以下命令: Measure-Command { .\your.exe }。显然,PowerShell 除非明确告知,否则不会从当前目录运行程序。 - Cristian Diaconescu
3
使用此命令powershell -Command Measure-Command { YOUR_COMMAND }不会隐藏stdout。它可以测量运行YOUR_COMMAND所需的时间。 - Behrouz.M
6
瑞·皮克斯误引用了弗拉基米尔的话。正确的应该是“Measure-Command { YOUR_COMMAND | Out-Default}”。 - Corey Levinson
显示剩余7条评论

379

如果你想:

  1. 以(hh:mm:ss.ff格式)精确到百分之一秒来测量执行时间
  2. 不需要下载和安装资源包
  3. 看起来像一个巨大的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小时或更长时间,则输出将不正确。


11
除非你的命令是另一个批处理文件,否则用 %* 替换 cmd /c %* 是可行的。如果命令是另一个批处理文件,则需要使用 timecmd call other.bat - Jesse Chisholm
4
出于某些原因,这个命令只会输出完整的秒数……对我来说毫无用处。我的意思是,当我运行 timecmd pause 命令时,它总是显示 1.00 秒、2.00 秒、4.00 秒……甚至是 0.00 秒!操作系统为 Windows 7。 - Camilo Martin
10
@CamiloMartin和其他遇到这个问题的人(包括我)-你可能使用的是一个以逗号而不是点作为小数点的语言环境。所以,在此脚本中,将“delims =:。”更改为“delims =:。,”,然后它就应该“全面运行”。 - Tomasz Gandor
5
该脚本中有一个严重的算术错误: 尝试使用以下命令: set start=10:10:10.10 set 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) - Jean-François Larvoire
3
对于任何想知道的人:TomaszGandor和Jean-FrançoisLarvoire所进行的修复已经被编辑到上述脚本中。还有 @Jashan:你的毫秒填充存在一个错误(实际上是百分之一秒),而你正在使用“secs”变量而不是“ms”,因此应该是:“set "ms=0%ms%"”和“set "ms=%ms:~-2%"”。除此之外,我喜欢这个! - Paul
显示剩余12条评论

279

呵呵,最简单的解决方案可能是这样的:

echo %time%
YourApp.exe
echo %time%

这在所有的Windows系统上都可以直接使用。


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

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

2
太棒了!尽管对于 CPU 时间来说并没有真正帮助。 - Ilya Saunkin
13
更好的方式(如果您的应用程序将输出发送到控制台):set startTime=%time% \n YourApp.exe \n echo 开始时间:%startTime% \n echo 完成时间:%time% - Jono
5
不,这是个不好的选择。它告诉你的是挂钟时间,而不是 CPU 时间。因此,即使你的命令行只需要 100 毫秒,如果有另一个应用程序独占了 CPU,你的应用程序可能需要花费几秒钟(误差超过 100 倍)。事实上,如果你的计算机正在抖动,甚至可能要等一分钟才能运行你那个只需要 100 毫秒的小应用程序。跟踪 CPU 时间,而不是挂钟时间! - Ryan Shillington
2
@MykhayloKopytonenko 可以的:echo %time% && YourCmd --with -- -params && echo %time% - DaJunkie
2
我知道我的答案没有计算执行时间。但请考虑到,当我在2010年3月编写答案时,最常见的Windows操作系统是Windows XP / Server 2003,这些系统默认没有安装PowerShell。上述解决方案可直接使用,无需安装其他软件(这在企业环境中特别有帮助)。 - LietKynes
显示剩余8条评论

128

这是对Casey.K的回答的一点扩展,关于如何使用Measure-Command工具来测试PowerShell脚本的性能:

  1. You can invoke PowerShell from the standard command prompt, like this:

    powershell -Command "Measure-Command {echo hi}"
    
  2. This will eat the standard output, but you can prevent that by adding | Out-Default like this from PowerShell:

    Measure-Command {echo hi | Out-Default}
    

    Or from a command prompt:

    powershell -Command "Measure-Command {echo hi | Out-Default}"
    
当然,您可以将其封装在脚本文件*.ps1*.bat中。

2
如果我们想测量的命令中包含引号该怎么办?在这种情况下,还能将其转化为 .bat 脚本吗?例如 measureTime.bat "c:\program files\some dir\program.exe" - GetFree

123

如果你正在使用Windows 2003(请注意,不支持Windows Server 2008及更高版本),你可以使用包含timeit.exe的Windows Server 2003资源工具包,它会显示详细的执行统计信息。以下是一个示例,用于计时命令"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资源工具包中获取TimeIt。它无法直接从Microsoft下载中心下载,但仍可以从archive.org - Windows Server 2003 Resource Kit Tools获取。


8
此套件在Windows 2008 64位系统中存在问题,且不兼容2008 R2系统。 - Artem
43
FYI - 我认为 timeit 在 Windows 7 64 位系统上不起作用。你会得到错误信息“无法查询系统性能数据(c0000004)”。相反,像 Casey.K 建议的那样,使用 PowerShell 的“Measure-Command”来测量命令执行时间。链接是:https://dev59.com/OXRB5IYBdhLWcg3wSVYI#4801509 - Michael La Voie
7
在Windows 7中,我看到“'timeit'未被识别为内部或外部命令、可执行程序或批处理文件。” - Colonel Panic
5
我在Windows 10中没有找到该命令,也没有轻松地找到适用于Win 10的资源工具包。有人知道如何在Win 10上获取它吗? - Jay Imerman
timeit.exe 在这里运行良好,Windows 10 x64。 - masterxilo
显示剩余2条评论

57

我在Windows Server 2008 R2上使用的一行命令是:

cmd /v:on /c "echo !TIME! & *mycommand* & echo !TIME!"
只要mycommand不需要引号(这会干扰cmd的引号处理),/v:on是为了允许两个不同的TIME值独立评估,而不是在执行命令时只评估一次。

这对于“垃圾邮件”批次也不起作用,它们会覆盖第一次标签,并意味着您需要更换执行计算的计算机,正如http://stackoverflow.com/questions/673523/how-to-measure-execution-time-of-command-in-windows-command-line#comment7229148_2417604中所述。 - Val
通常在cmd中,您可以通过使用^(例如^")来转义引号。 - n611x007
2
如果您在第二次运行时重复使用cmd /v:on,我们甚至可以让_mycommand_包含引号。例如:cmd /v:on /c echo !TIME! & echo "Quoted mycommand" & cmd /v:on /c echo !TIME! - Maarten Pennings
11
简化版:echo %time% & *mycommand* & call echo %^time%。另请参见此答案 - Aacini
@Aacini 这个方法成功了。我看到其他人也建议类似的方法,但没有使用 call^。那些方法不起作用。我的意思是,我得到了相同的结果。这个方法和它们之间有什么区别? - akinuri
显示剩余2条评论

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

prompt $d $t $_$P$G

它会给你类似于:

2009年3月23日15:45:50.77

C:\>

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

(空行)

myCommand.exe

(下一个空行)

myCommand2.exe

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

MyBatchFile.bat > output.txt

2
简单、优雅,无需安装,无需编写批处理文件即可执行一次命令,并能够计时批处理文件中的每个步骤。 - Matt

29

由于其他人推荐安装像免费软件和PowerShell这样的工具,你也可以安装Cygwin,这将使您能够访问许多基本的Unix命令,例如time

abe@abe-PC:~$ time sleep 5

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

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


我也点赞了这个答案,因为我发现这是最简单的解决方案,因为免费的程序Cmder包括bash!http://cmder.net/只需记住,在bash中如果需要转义空格,请在空格之前使用反斜杠\,而不是“引号”。例如,cd /c/Program\ Files/ - lukescammell
我是开发人员,使用WSL。%windir%\system32\wsl.exe -cur_console:pm:/mnt我们有一个Bash命令行 :-) - Quazer
请问 OP 能否提供一个在 CMD 脚本中实现此功能并测量该脚本持续时间的示例,最好是在脚本内部实现。 - Jon Grah

26
不像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:

2
假设您不需要跨不同语言的可移植性,您也可以在"time < nul"之后放置一个findstr "current"或类似的内容(顺便说一下,nul的使用很好;我一直使用echo.|time,但那看起来不太优雅:))。并使用“for”仅提取时间,而不是文本。 - Joey
2
如果启用了命令扩展(即默认情况下),Win XP 版本的 time 命令有一个 /t 选项,它只显示当前系统时间,而不提示您输入新时间。但是,当您这样做时,它只显示小时和分钟,这可能对某些用途不够好。 (请参见 John Snow 对此问题的回答。) - martineau
3
只有当进程运行几分钟时,"time /T" 命令才有效。如果想更加精确,可以使用 "time < nul" 命令,虽然它不太美观。 - PhiLho
7
您也可以使用 echo %time%,它提供与 time < nul 相同的格式和精度,但避免了 "输入新时间:" 的输出。 - aschipfl
为了使用与地区无关且更精确的时间,请使用“wmic os get LocalDateTime”。 - phuclv

21

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

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

timer
yourapp.exe
timer /s

如果您需要一组时间,请将timer /s的输出导入到一个.txt文件中。

您可以在此处获取:Gammadyne's免费DOS实用程序


分辨率为0.1秒。


4
我认为使用第三方应用程序不能被视为“标准手段”。 - martineau
5
问询者的意思是“不需要安装额外的软件”,但是顶部(被接受的)答案也需要安装一个完整的Windows 2003资源工具包!无论如何,timer.exe非常适合我现在正在寻找的,谢谢! - Hugo
我相信这对于任何使用 cmder 的人来说也是有效的。 - youngrrrr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接