Как измерить время выполнения цикла в пакетном файле

EDIT: * Может ли кто-нибудь помочь мне понять, почему переменная времени ведет себя именно так? Выход выглядит так:

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

Когда я запускаю свой пакетный файл с этими дополнениями, я получаю время начала и окончания (установленное до фактического запуска файла), которые равны друг другу, и они будут равны предыдущему времени начала и окончания из последней итерации и предстоящая итерация.

Есть идеи, в чем дело?


person David    schedule 12.12.2014    source источник
comment
Сделка, вероятно, отложена расширением. Измените @echo off на @echo on и посмотрите на вывод, чтобы увидеть, что на самом деле выполняется.   -  person indiv    schedule 12.12.2014
comment
Когда я повернул @ECHO ON, код сработал. В том смысле, что это не давало бесконечную серию STARTTIME: ENDTIME: Unbalanced Parenthesis, но я не знаю, почему установка @ECHO ON повлияет на выполнение скрипта. Кроме того, я понял, что до этого он указывал время начала и окончания, но устанавливал все времена начала и окончания как = времени запуска сценария. Таким образом, каждый цикл возвращает время начала и окончания того времени, которое было, когда я начал сценарий, и он возвращает это до того, как цикл, который я пытаюсь измерить, действительно выполняется.   -  person David    schedule 15.12.2014


Ответы (2)


В вашем коде

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 сантисекунд) к результирующей (отрицательной) длительности.

person Magoo    schedule 12.12.2014
comment
Интересно, что эти опечатки изолированы от моего поста здесь. Они не отображаются в реальном коде, но я просто скопировал и вставил. В любом случае, еще одна интересная проблема заключается в том, что время начала и время окончания объявляются до того, как процесс внутри rem here begins the command you want to measure и rem here ends the command you want to measure будет выполнен. Я бы подумал, что так, как я настроил код, будет объявлено время начала, а затем цикл пойдет, а затем будет объявлено время окончания. - person David; 15.12.2014
comment
Я думаю, что этот ответ можно улучшить, чтобы просто показать, как это сделать, и меньше фокусироваться на коде автора. - person Mike Q; 30.04.2020
comment
См. также эту ссылку: com/questions/9922498/ - person Mike Q; 30.04.2020

Как насчет использования правильного инструмента для работы.

Использование WPT для пакетного профилирования скриптов

Это должно дать вам более чем достаточно информации о ваших пакетных сценариях, и вы можете включить дополнительное профилирование выполняемых команд, если хотите выяснить, почему это происходит медленно.

person Alois Kraus    schedule 12.12.2014