【问题标题】:How to measure the execution time of a loop in a batch file如何测量批处理文件中循环的执行时间
【发布时间】:2014-12-12 19:08:27
【问题描述】:

编辑: *谁能帮我理解为什么时间变量的行为方式是这样的?结果是这样的:

c:\directory><
for /D /r %%F IN ("*") DO ( 
   for %%G  IN ("%%F\*.sdf") DO xcopy "%%G" c:\Path2\%newest% /y /i 
for /f "delims=_" %%J IN ('forfiles /p "%%F" /m *.extension /c "cmd /c echo @path"')  DO start "Program"  /D "c:\program files\Path2" /Wait jmpt -r  %%J
set ENDTIME=(whatever the current time is)
echo STARTTIME:
echo ENDTIME:
set /a DURATION=-
endlocal
rem this ends the runtime segment
>

所以我有一个批处理文件,它将使用 for 循环执行多个文件。我正在尝试添加一个脚本来测量每个文件执行所需的时间(而不是整个批处理文件)。或者换句话说,我想测量循环的每次迭代完成需要多长时间。一位同事给了我一个工作批处理时间度量,但是当我尝试将它实施到我的批处理文件中时,它会在运行的最开始设置开始和结束时间并且从不更新它。

这是他的批处理文件

@ECHO OFF
set PATH=%PATH%;C:\Path

set STARTTIME=%TIME%

rem here begins the command you want to measure
@ECHO %PATH%
rem here ends the command you want to measure
rem (I, the stackoverflow asker, just used @ECHO %PATH% to test if his script worked)

set ENDTIME=%TIME%

rem output as time
echo STARTTIME: %STARTTIME%
echo ENDTIME: %ENDTIME%

rem convert STARTTIME and ENDTIME to centiseconds
set /A STARTTIME=(1%STARTTIME:~0,2%-100)*360000 + (1%STARTTIME:~3,2%-100)*6000 + (1%STARTTIME:~6,2%-100)*100 + (1%STARTTIME:~9,2%-100)
set /A ENDTIME=(1%ENDTIME:~0,2%-100)*360000 + (1%ENDTIME:~3,2%-100)*6000 + (1%ENDTIME:~6,2%-100)*100 + (1%ENDTIME:~9,2%-100)

rem calculating the duratyion is easy
set /A DURATION=%ENDTIME%-%STARTTIME%

rem we might have measured the time in between days
if %ENDTIME% LSS %STARTTIME% set /A DURATION=%STARTTIME%-%ENDTIME%

rem now break the centiseconds down to hours, minutes, seconds and the remaining centiseconds
set /A DURATIONH=%DURATION% / 360000
set /A DURATIONM=(%DURATION% - %DURATIONH%*360000) / 6000
set /A DURATIONS=(%DURATION% - %DURATIONH%*360000 - %DURATIONM%*6000) / 100
set /A DURATIONHS=(%DURATION% - %DURATIONH%*360000 - %DURATIONM%*6000 - %DURATIONS%*100)

rem some formatting
if %DURATIONH% LSS 10 set DURATIONH=0%DURATIONH%
if %DURATIONM% LSS 10 set DURATIONM=0%DURATIONM%
if %DURATIONS% LSS 10 set DURATIONS=0%DURATIONS%
if %DURATIONHS% LSS 10 set DURATIONHS=0%DURATIONHS%

rem outputing
echo STARTTIME: %STARTTIME% centiseconds
echo ENDTIME: %ENDTIME% centiseconds
echo DURATION: %DURATION% in centiseconds
echo %DURATIONH%:%DURATIONM%:%DURATIONS%,%DURATIONHS%

endlocal

现在我的批处理文件看起来像这样(他实现了)

RMDIR c:\directory /s /q
mkdir c:\directory
xcopy "\\Path1\*" c:\directory /s /i
cd c:\Path2
for /f "tokens=*" %%a in ('dir /b /od') do set newest=%%a
cd c:\directory
sqlcmd -S Server -i "\\Path3\query1.sql"

for /D /r %%F IN ("*") DO ( 
   for %%G  IN ("%%F\*.sdf") DO xcopy "%%G" c:\Path2\%newest% /y /i 

@ECHO OFF

set STARTTIME=%TIME%

   for /f "delims=_" %%J IN ('forfiles /p "%%F" /m *.extension /c "cmd /c echo @path"')  DO start "Program"  /D "c:\program files\Path2" /Wait jmpt -r  %%J




set ENDTIME=%TIME%

rem output as time
echo STARTTIME: %STARTTIME%
echo ENDTIME: %ENDTIME%

rem convert STARTTIME and ENDTIME to centiseconds
set /A STARTTIME=(1%STARTTIME:~0,2%-100)*360000 + (1%STARTTIME:~3,2%-100)*6000 (1%STARTTIME:~6,2%-100)*100 + (1%STARTTIME:~9,2%-100)
set /A ENDTIME=(1%ENDTIME:~0,2%-100)*360000 + (1%ENDTIME:~3,2%-100)*6000 + (1%ENDTIME:~6,2%-100)*100 + (1%ENDTIME:~9,2%-100)

rem calculating the duratyion is easy
set /A DURATION=%ENDTIME%-%STARTTIME%

rem we might have measured the time inbetween days
if %ENDTIME% LSS %STARTTIME% set set /A DURATION=%STARTTIME%-%ENDTIME%

rem now break the centiseconds down to hors, minutes, seconds and the remaining centiseconds
set /A DURATIONH=%DURATION% / 360000
set /A DURATIONM=(%DURATION% - %DURATIONH%*360000) / 6000
set /A DURATIONS=(%DURATION% - %DURATIONH%*360000 - %DURATIONM%*6000) / 100
set /A DURATIONHS=(%DURATION% - %DURATIONH%*360000 - %DURATIONM%*6000 - %DURATIONS%*100)

rem some formatting
if %DURATIONH% LSS 10 set DURATIONH=0%DURATIONH%
if %DURATIONM% LSS 10 set DURATIONM=0%DURATIONM%
if %DURATIONS% LSS 10 set DURATIONS=0%DURATIONS%
if %DURATIONHS% LSS 10 set DURATIONHS=0%DURATIONHS%

rem outputing
echo STARTTIME: %STARTTIME% centiseconds
echo ENDTIME: %ENDTIME% centiseconds
echo DURATION: %DURATION% in centiseconds
echo %DURATIONH%:%DURATIONM%:%DURATIONS%,%DURATIONHS%


endlocal
)

sqlcmd -S Server -i "\\path3\query2.sql"

pause

当我使用这些添加运行我的批处理文件时,我得到一个开始和结束时间(在文件实际开始运行之前设置),它们彼此相等,它们将等于上一个开始和结束时间迭代和即将到来的迭代。

有什么想法吗?

【问题讨论】:

  • 这笔交易可能是延迟扩张。将 @echo off 更改为 @echo on 并查看输出以了解实际运行的内容。
  • 当我打开@ECHO ON 时,代码“有效”。从某种意义上说,它没有给出无穷无尽的STARTTIME: ENDTIME: Unbalanced Parenthesis 系列,但我不知道为什么设置@ECHO ON 会影响脚本的性能。另外,我意识到它在此之前已经给出了开始和结束时间,但是它将所有开始和结束时间设置为 = 脚本开始的时间。因此,每个循环都会返回我开始脚本时的任何时间的开始和结束时间,并且它会在我尝试测量的循环实际执行之前返回。

标签: windows batch-file time cmd batch-processing


【解决方案1】:

在您的代码中,

set /A STARTTIME=(1%STARTTIME:~0,2%-100)*360000 + (1%STARTTIME:~3,2%-100)*6000 (1%STARTTIME:~6,2%-100)*100 + (1%STARTTIME:~9,2%-100)

您在*6000 之后缺少+

set /A STARTTIME=(1%STARTTIME:~0,2%-100)*360000 + (1%STARTTIME:~3,2%-100)*6000 + (1%STARTTIME:~6,2%-100)*100 + (1%STARTTIME:~9,2%-100)

在原代码中:

if %ENDTIME% LSS %STARTTIME% set set /A DURATION=%STARTTIME%-%ENDTIME%

set 被重复 - 显然,该代码从未在午夜进行过测试。

在这两种情况下,如果endime 小于starttime,正确的计算是在结果(负)持续时间上加上 3600*2400(3600 秒/小时 * 24 小时/天 * 100 厘秒)。

【讨论】:

  • 有趣的是,这些错别字在我的帖子中是孤立的。它们没有出现在实际代码中,但我只是复制并粘贴了.. 无论如何,另一个有趣的问题是在 rem here begins the command you want to measurerem here ends the command you want to measure 内的进程执行之前声明了开始时间和结束时间。我认为我设置代码的方式是声明开始时间,然后循环开始,然后声明结束时间。
  • 我认为这个答案可以改进,只展示如何做到这一点,而不是关注海报的代码。
  • 也可以查看此链接stackoverflow.com/questions/9922498/…
【解决方案2】:

如何为工作使用正确的工具。

Using WPT For Batch Script Profiling

这应该让您对批处理脚本有足够的了解,如果您想找出执行命令缓慢的原因,您可以打开对已执行命令的额外分析。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 2015-01-17
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多