1 (изменено: Аскет, 2012-12-31 01:53:22)

Тема: CMD/BAT: BenchMark времени выполнения

Ёу-хоу-хоу, а вот и дед Мороз с подарками
Вот и подошла к концу астрологическая эра Рыб, а вместе с ней и "Ночь Сварога", с сопутствующим ей "ментальным сном". Давайте ворвёмся в Чертог Волка с радостным настроением. В путь товар'ищи.
С наступающим 2013!


Представляю вашему вниманию уникальную разработку. Это преполезнейший отладочный скрипт!
Он может быть использован как при  разработке/доводке/отладке/выборе алгоритма (поиске оптимального пути), так и при повседневном использовании.

Суть такова: у нас есть некое действо, которое надо выполнить, и затем показать сколько это действо затратило времени (а потом сравнить с подобным и выбрать самое быстрое, например)

"Действо" задаётся параметром запуска скрипта: команда, последовательность команд (через & и Ко.), программа или скрипт.

spendRunTimer.bat команда_скрипт_или_программа [параметы]

Для того чтобы использовать  разделитель-амперсенд и операторы перенаправления (&,<,>,|) как часть исследуемой последовательности команд, перед ними необходимо записать три шляпы: ^^^&,^^^>NUL,...
Например, если требуется подавить вывод исследуемой команды, и только замерить время, то следует запускать с таким параметром:

spendRunTimer COMMAND ^^^>NUL

>spendRunTimer.bat PING -n 2 LOCALHOST ^^^>nul
______________________________
Spending of RunTime = [00:00:01,09]
...
>spendRunTimer.bat echo Ascetic technologies
Ascetic technologies
______________________________
Spending of RunTime = [00:00:00,00]

spendRunTimer.bat:

:: [Examples]
:: command: spendRunTimer dir
:: program: spendRunTimer program.exe [params]
:: script: spendRunTimer mybatch.cmd
:: using caps for "<,>,|,&" : spendRunTimer COMMAND ^^^>NUL

::@================================================================
::    Name:         SpendRunTimer.bat (SRT)
::    Language:     Win-batch
::    CommandLine: spendRunTimer.bat [Any Commandline]
::    Author:         Аскет, 2009-2011. [true-script(at)ya.ru]
::    last upd:     31/12/2012 г.
::    Description: This debugging script is intended for remark of time, spent
::                     on execution other script or any command.
::                    Precision: milisecond.
::                    Single faithfull way of at searching of optimum solution.
::    Using:        For "one-string" inline scripts and specific command you must screening control symbols three caps "^^^"
::
::    [Examples]
::            command:                        spendRunTimer 
::            program:                        spendRunTimer program.exe [params]
::            script:                            spendRunTimer mybatch.cmd
::            using caps for "<,>,|,&" :        spendRunTimer COMMAND ^^^>NUL
::            inline-script:                    spendRunTimer ping -n 6 localhost^^^>nul ^^^& echo WelcomTo! ^^^& msg * hello world!
::            OR:                            spendRunTimer (echo EHLO HELLO WORLD! ^^^& msg * hello world!^^^& NET SEND * HELLO WORLD!^^^& NET SEND * HELLO %^USERNAME%,  %USERNAME% IS WATCHING YOU! SHUTDOWN YOUR PC!)
::@================================================================
@echo off
SET CMD=%*
IF NOT DEFINED CMD (EXIT /B)
=================:: [MAIN] ::========================
SET T1=%time%

%CMD%

SET T2=%time%
:: But you should know the Russian language! Because english - wrong and ugly language. So has said Master.
==================:: [/MAIN] ::========================

    ::--------------- РАЗБИЕНИЕ МЕТОК ВРЕМЕНИ НА РАЗРЯДЫ [чч,мм,сс] -------------
for /f "tokens=1-4 delims=:," %%a in ("%T1%") do (set h1=%%a & set m1=%%b & set s1=%%c & set ms1=%%d)
for /f "tokens=1-4 delims=:," %%a in ("%T2%") do (set h2=%%a & set m2=%%b & set s2=%%c & set ms2=%%d)
    ::--------------- СЕРИАЛИЗАЦИЯ -------------
set /a T1 = (h1*360000)+(m1*6000)+(s1*100)+ms1
set /a T2 = (h2*360000)+(m2*6000)+(s2*100)+ms2
    ::--------------- ВЫЧИСЛЕНИЕ -------------
set /a T3 = T2-T1
    ::--------------- ДеСЕРИАЛИЗАЦИЯ [muchSS -> hh,mm,ss] -------------
    ::hour
set /a H = T3/360000
set /a T3 -= (H*360000)
    ::minute
set /a M = T3/6000
set /a T3 -= (M*6000)
    ::second
set /a S = T3/100
    ::milisecond
set /a MS = T3-(S*100)
    ::--------------- ФОРМАТНАЯ КОРРЕКТИРОВКА РЕЗУЛЬТАТОВ -------------
 CALL :CheckNum %H%,H
 CALL :CheckNum %M%,M
 CALL :CheckNum %S%,S
 CALL :CheckNum %MS%,MS

set spendRunTime=%H%:%M%:%S%,%MS%
::show result
echo ______________________________
ECHO/Spending of RunTime = [%spendRunTime%]


EXIT /B
======================
:CheckNum (varIN,varOUT)
    set /A temp_ = %1
    if "%temp_:~1,1%"=="" (SET %2=0%temp_%)
EXIT /B
======================

На самом деле он короче, чем кажется, - комментарии.

2 (изменено: Arigato, 2013-01-01 07:57:32)

Re: CMD/BAT: BenchMark времени выполнения

Тут скрывается неприятная ошибка: set /a T1 = (h1*360000)+(m1*6000)+(s1*100)+ms1
m1, s1 и ms1 могут начинаться с нуля (например, time = 12:03:09,07
Числа, начинающиеся с нуля, воспринимаются как восмеричные. И если с числами 03 и 07 проблем не будет, то на 09 cmd ответит так:

Неправильное число. Числовые константы должны быть де
шестнадцатеричными (0x11),или восьмеричными (021).

Ну и идея небольшой оптимизации. Вместо такого:

set /a H = T3/360000
set /a T3 -= (H*360000)

Можно писать так:

set /a H = T3/360000
set /a T3 %%= 360000

3

Re: CMD/BAT: BenchMark времени выполнения

Вариант, как избежать эту ошибку:

@ echo off
setlocal enabledelayedexpansion

call :gettick
echo Tick Count: %errorlevel%

pause
exit /b 0

:gettick
:: Количество сотых долей секунды, прошедших с начала дня
setlocal
set t=%time: =0%
set /a tick=1%t:~9,2%-100+(1%t:~6,2%-100)*100+(1%t:~3,2%-100)*6000+(1%t:~0,2%-100)*360000
endlocal & exit /b %tick%

Функция gettick возвращает количество сотых долей секунды, прошедших с начала дня. Чтобы не появилось "восьмеричных" чисел, я дописываю к каждой компоненте времени в начало 1, а затем вычитаю 100. Таким образом проблема решается без введение дополнительных поверок if.