Сколько времени занимает выполнение командного файла? - PullRequest
18 голосов
/ 11 апреля 2009

Как мне написать сценарий для расчета времени, которое потребовалось для выполнения сценария?

Я думал, что это будет так, но, очевидно, нет ..

@echo off
set starttime=%time%
set endtime=%time%

REM do stuff here

set /a runtime=%endtime%-%starttime%
echo Script took %runtime% to complete

Ответы [ 6 ]

38 голосов
/ 11 апреля 2009

В исходном пакетном файле выпрыгивают две вещи. , но ни один из них не поможет в долгосрочной перспективе.

  1. Каким бы ни был ваш метод тестирования, обязательно запишите время начала до операции и время окончания после операции. Ваш образец не делает этого.

  2. %time% оценивается как «12: 34: 56.78», и команда SET /A не может их вычесть. Вам нужна команда, которая производит простую скалярную метку времени.

Я собирался сказать, что это невозможно, но пакетный язык намного мощнее, чем его считают, так что здесь есть простая реализация TIMER.BAT. Для протокола, Пакс избил меня до ответа, показывающего расщепление струны, пока я возился, и Йоханнес Рессел предложил переместить арифметику за пределы измеряемой области:

@echo off
setlocal

rem Remeber start time. Note that we don't look at the date, so this
rem calculation won't work right if the program run spans local midnight.
set t0=%time: =0%

rem do something here.... but probably with more care about quoting.
rem specifically, odd things will happen if any arguments contain 
rem precent signs or carets and there may be no way to prevent it.
%*

rem Capture the end time before doing anything else
set t=%time: =0%

rem make t0 into a scaler in 100ths of a second, being careful not 
rem to let SET/A misinterpret 08 and 09 as octal
set /a h=1%t0:~0,2%-100
set /a m=1%t0:~3,2%-100
set /a s=1%t0:~6,2%-100
set /a c=1%t0:~9,2%-100
set /a starttime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c%

rem make t into a scaler in 100ths of a second
set /a h=1%t:~0,2%-100
set /a m=1%t:~3,2%-100
set /a s=1%t:~6,2%-100
set /a c=1%t:~9,2%-100
set /a endtime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c%

rem runtime in 100ths is now just end - start
set /a runtime = %endtime% - %starttime%
set runtime = %s%.%c%

echo Started at %t0%
echo Ran for %runtime%0 ms

Вы могли бы упростить арифметику и быть немного более честным в отношении общей точности этого, не беспокоясь о сотых долях второй части. Вот он в действии, при условии, что у вас есть команда сна или какой-то другой тратит время:

C:> TIMER SLEEP 3
Script took 3000 ms to complete
C:> 

Редактировать: Я изменил код и его описание, как это предлагается в комментарии.

Я думаю, что когда команда NT заменила COMMAND.COM на CMD.EXE, они подумали, что им не удастся сделать его совсем другим. Но на самом деле это почти совершенно новый язык. Многие из старых любимых команд имеют новые функции, если расширения включены.

Одним из них является SETLOCAL, который не позволяет переменным изменять среду вызывающего. Другой - SET /A, который дает вам замечательное количество арифметики. Принцип, который я использовал здесь, - это новый синтаксис извлечения подстрок, где %t:~3,2% означает два символа, начинающиеся со смещения 3 в значении переменной с именем t.

Для настоящего шокера взгляните на полное описание набора (попробуйте SET /? в приглашении), и если вас это не пугает, посмотрите на FOR /? и обратите внимание, что он может анализировать текст из файлов. ...

Редактировать 2: Исправлена ​​неправильная обработка полей времени, содержащих 08 или 09, о которых сообщил Фрэнки в комментариях. Подправил пару вещей и добавил несколько комментариев.

Обратите внимание, что здесь есть явный недосмотр, который я, вероятно, не собираюсь исправлять. Это не будет работать, если команда начинается в другой день, чем она заканчивается. То есть он будет выполнять некоторые математические операции, связанные со временем суток, и сообщать о разнице, но разница не будет много значить.

Исправить это, по крайней мере, предупредить об этом случае легко. Исправить это, чтобы сделать правильные вещи сложнее.

Редактировать 3: Исправлена ​​ошибка, при которой% h% не был установлен правильно для однозначных часов. Это связано с тем, что% time% возвращает «9: 01: 23.45». Обратите внимание на пространство. Использование% time: = 0% заменяет пробел на начальный ноль, и% h% будет установлен правильно. Эта ошибка возникала только в том случае, если сценарий выполнялся с одного однозначного часа до следующего.

4 голосов
/ 11 апреля 2009

Это своего рода тангенциальное, но может помочь вам.

В Microsoft есть программа timeit.exe, которая работает более или менее как расширенная версия команды unix 'time'. Он входит в комплект Windows Server 2003 Resource Kit и заменяет его во все времена, когда я хотел сделать что-то вроде того, что вы предлагаете.

Может быть стоит посмотреть.

3 голосов
/ 31 октября 2012

Отличная маленькая рутина. Однако, если расчет охватывает два дня, он неверен. Результат нужно вычесть из 24 часов (8640000 центсекунд).

Также удалите одну из дублирующих команд «set» в соответствующей строке.

Обратите внимание, что региональные настройки влияют на формат функции ВРЕМЯ, причем десятичная дробь в Великобритании является точкой полного останова, а не запятой.

Линии

rem мы могли бы измерить время между днями

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

нужно изменить на

rem мы могли бы измерить время по дням

if %ENDTIME% LSS %STARTTIME% set /A DURATION=8640000 - (%STARTTIME% - %ENDTIME%)
2 голосов
/ 11 марта 2011

Проверьте этот скрипт, который будет извлекать время через WMI, поэтому он не зависит от региональных настроек.

@echo off
::::::::::::::::::::::::::::::::::::::::::
::  TimeDiff v1.00 by LEVENTE ROG       ::
::       www.thesysadminhimself.com     ::
::::::::::::::::::::::::::::::::::::::::::
 
::[ EULA ]:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::  Feel free to use this script. The code can be redistributed  ::
::  and edited, but please keep the credits.                     ::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
::[ CHANGELOG ]::::::::::::::
::  v1.00 - First Version  ::
:::::::::::::::::::::::::::::
 
 
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."') DO (
 set Milisecond=%time:~9,2% 
 set Day=%%A
 set Hour=%%B
 set Minute=%%C
 set Second=%%D
)
set /a Start=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100+%Milisecond%
 
::
::
:: PUT COMMANDS HERE
ping www.thesysadminhimself.com
::
::
 
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."') DO (
 set Day=%%A
 set Hour=%%B
 set Minute=%%C
 set Second=%%D
)
set Milisecond=%time:~9,2% 
set /a End=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100+%Milisecond%
set /a Diff=%End%-%Start%
set /a DiffMS=%Diff%%%100
set /a Diff=(%Diff%-%DiffMS%)/100
set /a DiffSec=%Diff%%%60
set /a Diff=(%Diff%-%Diff%%%60)/60
set /a DiffMin=%Diff%%%60
set /a Diff=(%Diff%-%Diff%%%60)/60
set /a DiffHrs=%Diff%
 
:: format with leading zeroes
if %DiffMS% LSS 10 set DiffMS=0%DiffMS!%
if %DiffSec% LSS 10 set DiffMS=0%DiffSec%
if %DiffMin% LSS 10 set DiffMS=0%DiffMin%
if %DiffHrs% LSS 10 set DiffMS=0%DiffHrs%
 
echo %DiffHrs%:%DiffMin%:%DiffSec%.%DiffMS%
2 голосов
/ 11 апреля 2009

Мое личное предпочтение - установить Cygwin и использовать команду time, но, если у вас есть , чтобы сделать это как пакетный файл, вы не можете просто вычесть строки, вы должны относиться к ним как к частям.

Следующий скрипт рассчитает 10-секундную команду пинга с возможностью пересечения границы одного дня без привязки к отрицательным числам. Небольшое улучшение позволит ему пересечь многие дневные границы.

@echo off
setlocal enableextensions enabledelayedexpansion
set starttime=%time%
ping -n 11 127.0.0.1 >nul: 2>nul:
set endtime=%time%

set /a hrs=%endtime:~0,2%
set /a hrs=%hrs%-%starttime:~0,2%

set /a mins=%endtime:~3,2%
set /a mins=%mins%-%starttime:~3,2%

set /a secs=%endtime:~6,2%
set /a secs=%secs%-%starttime:~6,2%

if %secs% lss 0 (
    set /a secs=!secs!+60
    set /a mins=!mins!-1
)
if %mins% lss 0 (
    set /a mins=!mins!+60
    set /a hrs=!hrs!-1
)
if %hrs% lss 0 (
    set /a hrs=!hrs!+24
)
set /a tot=%secs%+%mins%*60+%hrs%*3600

echo End     = %endtime%
echo Start   = %starttime%
echo Hours   = %hrs%
echo Minutes = %mins%
echo Seconds = %secs%
echo Total   = %tot%

endlocal
1 голос
/ 11 апреля 2009

Вы не можете выполнять арифметику времени непосредственно в пакетном сценарии, поэтому вам потребуется либо внешняя программа для расчета разницы во времени, либо извлечение каждой части времени и выполнение арифметики таким образом.

Посмотрите на нижнюю часть этой ветки форума , чтобы узнать, как это сделать. Выдержка здесь:

@echo off
cls
REM ================================================== ======
REM = Setting Date Time Format =
REM ================================================== ======
set DT=%DATE% %TIME%
set year=%DT:~10,4%
set mth=%DT:~4,2%
set date=%DT:~7,2%
set hour=%DT:~15,2%
set min=%DT:~18,2%
set sec=%DT:~21,2%
set newDT=%year%_%mth%_%date% %hour%%min%%sec%

set hour=14
set min=10

REM ===============================
REM = Getting End Time =
REM ===============================
set EndTime=%TIME%
set EndHour=%EndTime:~0,2%
set EndMin=%EndTime:~3,2%


REM ===============================
REM = Finding Difference =
REM ===============================
set /a Hour_Diff=EndHour - hour >nul
set /a Min_Diff=EndMin - min >nul


REM ===============================
REM = Hour Hand Change? =
REM ===============================
IF [%Hour_Diff]==[0] (

Set Duration=%Min_Diff%
) ELSE (

Set /a Duration=60-%Min_Diff% >nul
)


echo Start Time = %hour% : %min%
echo End Time = %EndHour% : %EndMin%
echo.
echo Min Diff = %Min_Diff%
echo.
echo time difference (mins) = %Duration%

Я также предполагаю, что это опечатка, но вы обязательно должны установить endtime после обработки .

...