为什么GOTO循环比FOR循环慢得多,并且还取决于电源? [英] Why is a GOTO loop much slower than a FOR loop and depends additionally on power supply?

查看:94
本文介绍了为什么GOTO循环比FOR循环慢得多,并且还取决于电源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个小批处理文件,将每行包含八个16位十六进制值的文件转换为十进制八个值的CSV文件.

输入数据文件是捕获的嵌入式设备ADC值的输出,以ASCII形式的八个十六进制值的数据包以回车符加上通过RS-232到PC的换行符发送到PC,并简单地在PC上捕获到文件中.输入数据文件中的一行类似于:

000A002D0044008B0125018C01F40237

此行的CSV文件为:

10,45,68,139,293,396,500,567

该批处理文件有效,但是花了几分钟才完成转换,这令我震惊.我期望Windows命令处理器完成此任务需要花费几秒钟的时间,而用C或C ++编写的控制台应用程序可能需要几秒钟的时间.但是我绝对不希望对小于512 KiB的数据文件执行几分钟的时间.

因此,我通过使用四种不同的方法来创建批处理文件以从具有十六进制值的数据文件中创建具有十进制值的CSV文件来进一步解决这个问题.

下面是用于测试这四种方法的完整批处理文件以及我的测试结果.

我了解到,使用子例程的前两种方法要比后两种方法在一个循环中进行转换要慢得多,后者在 FOR 结束时在每次循环迭代中分别将每条CSV行分别输出到文件中>循环,因为调用子例程会导致cmd.exe完成几个额外的步骤,而这些子例程在执行数千次子例程调用时总共要花费很多时间.

但是我真的不明白为什么使用 GOTO 循环的第一种方法比使用几乎相同的两个命令行的 FOR 循环慢大约六倍.

方法1的批处理文件代码:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "DelDataFile="
set "DataFile=%TEMP%\HexValues.dat"
if not exist "%DataFile%" set "DelDataFile=1" & echo 000A002D0044008B0125018C01F40237>"%DataFile%"

for /F "usebackq delims=" %%I in ("%DataFile%") do call :ConvertLine "%%I"

if defined DelDataFile del "%DataFile%"
endlocal
goto :EOF

:ConvertLine
set "DataLine=%~1"
set "AllValues="
set "StartColumn=0"
:NextValue
set /A Value=0x!DataLine:~%StartColumn%,4!
set "AllValues=%AllValues%,%Value%"
set /A StartColumn+=4
if not %StartColumn% == 32 goto NextValue
echo %AllValues:~1%
goto :EOF

方法2的批处理文件代码:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "DelDataFile="
set "DataFile=%TEMP%\HexValues.dat"
if not exist "%DataFile%" set "DelDataFile=1" & echo 000A002D0044008B0125018C01F40237>"%DataFile%"

for /F "usebackq delims=" %%I in ("%DataFile%") do call :LineConvert "%%I"

if defined DelDataFile del "%DataFile%"
endlocal
goto :EOF

:LineConvert
set "DataLine=%~1"
set "AllValues="
for /L %%J in (0,4,28) do (
    set /A Value=0x!DataLine:~%%J,4!
    set "AllValues=!AllValues!,!Value!"
)
echo !AllValues:~1!
goto :EOF

我还通过运行测试发现了一个原因,我自己发现方法1在使用电池供电的PC上比在插入电源的情况下花费5到10秒的时间.

问题:

与方法2使用的 FOR 循环相比,方法1使用的 GOTO 循环执行慢得多的原因是什么?为什么方法1依赖于PC的电源类型是什么?


以下是整个批处理文件,用于比较不同的方法:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
cls
set "TestRuns=5"
set "DelDataFile="
set "DataFile=%TEMP%\HexValues.dat"
if exist "%DataFile%" goto InitMethod1

set "DelDataFile=1"
echo Creating data file which takes some seconds, please wait ...
setlocal
set "HexDigits=0123456789ABCDEF"
set "DataLine="
(for /L %%I in (0,1,32767) do (
    set /A "Digit1=(%%I >> 12) %% 16"
    set /A "Digit2=(%%I >> 8) %% 16"
    set /A "Digit3=(%%I >> 4) %% 16"
    set /A "Digit4=%%I %% 16"
    set "HexValue="
    for %%J in (!Digit1! !Digit2! !Digit3! !Digit4!) do set "HexValue=!HexValue!!HexDigits:~%%J,1!"
    set "DataLine=!DataLine!!HexValue!"
    set /A "ValuesPerLine=%%I %% 8"
    if !ValuesPerLine! == 7 (
        echo !DataLine!
        set "DataLine="
    )
))>"%DataFile%"
endlocal
echo/


:InitMethod1
call :MethodInit 1
:RunMethod1
set /A TestRun+=1
set "CSV_File=%TEMP%\Values%Method%_%TestRun%.csv"
del "%CSV_File%" 2>nul
call :GetTime StartTime

for /F "usebackq delims=" %%I in ("%DataFile%") do call :ConvertLine "%%I"

call :OutputTime
if %TestRun% LSS %TestRuns% goto RunMethod1
call :MethodResults
goto InitMethod2

:ConvertLine
set "DataLine=%~1"
set "AllValues="
set "StartColumn=0"
:NextValue
set /A Value=0x!DataLine:~%StartColumn%,4!
set "AllValues=%AllValues%,%Value%"
set /A StartColumn+=4
if not %StartColumn% == 32 goto NextValue
>>"%CSV_File%" echo %AllValues:~1%
goto :EOF


:InitMethod2
call :MethodInit 2
:RunMethod2
set /A TestRun+=1
set "CSV_File=%TEMP%\Values%Method%_%TestRun%.csv"
del "%CSV_File%" 2>nul
call :GetTime StartTime

for /F "usebackq delims=" %%I in ("%DataFile%") do call :LineConvert "%%I"

call :OutputTime
if %TestRun% LSS %TestRuns% goto RunMethod2
call :MethodResults
goto InitMethod3

:LineConvert
set "DataLine=%~1"
set "AllValues="
for /L %%J in (0,4,28) do (
    set /A Value=0x!DataLine:~%%J,4!
    set "AllValues=!AllValues!,!Value!"
)
echo !AllValues:~1!>>"%CSV_File%"
goto :EOF


:InitMethod3
call :MethodInit 3
:RunMethod3
set /A TestRun+=1
set "CSV_File=%TEMP%\Values%Method%_%TestRun%.csv"
del "%CSV_File%" 2>nul
call :GetTime StartTime

for /F "usebackq delims=" %%I in ("%DataFile%") do (
    set "DataLine=%%I"
    set "AllValues="
    for /L %%J in (0,4,28) do (
        set /A Value=0x!DataLine:~%%J,4!
        set "AllValues=!AllValues!,!Value!"
    )
    echo !AllValues:~1!>>"%CSV_File%"
)

call :OutputTime
if %TestRun% LSS %TestRuns% goto RunMethod3
call :MethodResults
goto InitMethod4


:InitMethod4
call :MethodInit 4
:RunMethod4
set /A TestRun+=1
set "CSV_File=%TEMP%\Values%Method%_%TestRun%.csv"
del "%CSV_File%" 2>nul
call :GetTime StartTime

(for /F "usebackq delims=" %%I in ("%DataFile%") do (
    set "DataLine=%%I"
    set "AllValues="
    for /L %%J in (0,4,28) do (
        set /A Value=0x!DataLine:~%%J,4!
        set "AllValues=!AllValues!,!Value!"
    )
    echo !AllValues:~1!
))>>"%CSV_File%"

call :OutputTime
if %TestRun% LSS %TestRuns% goto RunMethod4
call :MethodResults
goto EndBatch


:GetTime
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "%1=%%I"
goto :EOF

:MethodInit
set "Method=%1"
echo Test runs with method %Method%
echo -----------------------
echo/
set "TestRun=0"
set "TotalTime=0"
goto :EOF

:MethodResults
set /A AverageTime=TotalTime / TestRun
echo Method %Method% total time: %TotalTime% seconds
echo Method %Method% average time: %AverageTime% seconds
echo/
goto :EOF

:OutputTime
call :GetTime EndTime
set /A StartTime=(1%StartTime:~8,2% - 100) * 3600 + (1%StartTime:~10,2% - 100) * 60 + 1%StartTime:~12,2% - 100
set /A EndTime=(1%EndTime:~8,2% - 100) * 3600 + (1%EndTime:~10,2% - 100) * 60 + 1%EndTime:~12,2% - 100
set /A DiffTime=EndTime - StartTime
set /A TotalTime+=DiffTime
echo Method %Method% run %TestRun% time: %DiffTime% seconds
goto :EOF


:EndBatch
if defined DelDataFile del "%DataFile%"
del /Q "%TEMP%\Values?_*.csv"
endlocal

它首先为临时文件创建文件夹中具有递增十六进制值的数据文件,该文件已经花费了几秒钟的时间.请批注此批处理文件的最后一条命令行以保留该文件,以防多次运行此批处理文件或对该文件感兴趣.

然后,它运行四种方法的五倍,这四种方法用于从数据文件读取十六进制值并将十进制值写入CSV文件,然后将测试结果打印到控制台,分别处理 STDOUT .

最后,它将删除也在文件夹中为所有具有相同内容的临时文件创建的所有CSV文件.请最后注释一个命令行,以使这些CSV文件保持对这些文件的兴趣.

这个批处理文件由我在两个笔记本上执行了四次.

以下是首次在具有2.26 GHz英特尔酷睿Duo P8400和2 GiB RAM和7200 rpm HDD的笔记本电脑上运行Windows XP x86并插入电源的笔记本电脑上运行的结果:

Test runs with method 1
-----------------------

Method 1 run 1 time: 51 seconds
Method 1 run 2 time: 51 seconds
Method 1 run 3 time: 51 seconds
Method 1 run 4 time: 52 seconds
Method 1 run 5 time: 51 seconds
Method 1 total time: 256 seconds
Method 1 average time: 51 seconds

Test runs with method 2
-----------------------

Method 2 run 1 time: 9 seconds
Method 2 run 2 time: 9 seconds
Method 2 run 3 time: 9 seconds
Method 2 run 4 time: 8 seconds
Method 2 run 5 time: 9 seconds
Method 2 total time: 44 seconds
Method 2 average time: 9 seconds

Test runs with method 3
-----------------------

Method 3 run 1 time: 3 seconds
Method 3 run 2 time: 3 seconds
Method 3 run 3 time: 4 seconds
Method 3 run 4 time: 3 seconds
Method 3 run 5 time: 3 seconds
Method 3 total time: 16 seconds
Method 3 average time: 3 seconds

Test runs with method 4
-----------------------

Method 4 run 1 time: 3 seconds
Method 4 run 2 time: 2 seconds
Method 4 run 3 time: 2 seconds
Method 4 run 4 time: 2 seconds
Method 4 run 5 time: 2 seconds
Method 4 total time: 11 seconds
Method 4 average time: 2 seconds

方法2比方法1快5.67倍.方法3和4甚至比方法2快,但这是我所期望的.方法3和4所需的2秒和3秒大部分来自 WMIC 命令,以采用与区域无关的格式获取本地日期和时间.

以下是第二次在与第一次运行相同的计算机上运行的结果,不同之处在于在充满电的电池下运行PC:

Test runs with method 1
-----------------------

Method 1 run 1 time: 63 seconds
Method 1 run 2 time: 61 seconds
Method 1 run 3 time: 61 seconds
Method 1 run 4 time: 61 seconds
Method 1 run 5 time: 61 seconds
Method 1 total time: 307 seconds
Method 1 average time: 61 seconds

Test runs with method 2
-----------------------

Method 2 run 1 time: 11 seconds
Method 2 run 2 time: 10 seconds
Method 2 run 3 time: 10 seconds
Method 2 run 4 time: 10 seconds
Method 2 run 5 time: 10 seconds
Method 2 total time: 51 seconds
Method 2 average time: 10 seconds

Test runs with method 3
-----------------------

Method 3 run 1 time: 3 seconds
Method 3 run 2 time: 4 seconds
Method 3 run 3 time: 3 seconds
Method 3 run 4 time: 4 seconds
Method 3 run 5 time: 3 seconds
Method 3 total time: 17 seconds
Method 3 average time: 3 seconds

Test runs with method 4
-----------------------

Method 4 run 1 time: 2 seconds
Method 4 run 2 time: 2 seconds
Method 4 run 3 time: 2 seconds
Method 4 run 4 time: 2 seconds
Method 4 run 5 time: 2 seconds
Method 4 total time: 10 seconds
Method 4 average time: 2 seconds

可以看出,对于方法2到方法4,处理时间只会增加一点点.但是方法1的处理时间增加了10秒,因此,该解决方案现在比方法2慢6.10倍.我不知道为什么方法1的处理时间取决于电源的类型.

这是首次在笔记本电脑上运行的结果,该笔记本电脑具有2.80 GHz的Intel Core Duo T9600和4 GiB RAM,以及运行Windows 7 x64且插入电源的固态硬盘:

Test runs with method 1
-----------------------

Method 1 run 1 time: 91 seconds
Method 1 run 2 time: 88 seconds
Method 1 run 3 time: 77 seconds
Method 1 run 4 time: 77 seconds
Method 1 run 5 time: 78 seconds
Method 1 total time: 411 seconds
Method 1 average time: 82 seconds

Test runs with method 2
-----------------------

Method 2 run 1 time: 11 seconds
Method 2 run 2 time: 16 seconds
Method 2 run 3 time: 16 seconds
Method 2 run 4 time: 14 seconds
Method 2 run 5 time: 16 seconds
Method 2 total time: 73 seconds
Method 2 average time: 14 seconds

Test runs with method 3
-----------------------

Method 3 run 1 time: 6 seconds
Method 3 run 2 time: 4 seconds
Method 3 run 3 time: 4 seconds
Method 3 run 4 time: 4 seconds
Method 3 run 5 time: 6 seconds
Method 3 total time: 24 seconds
Method 3 average time: 4 seconds

Test runs with method 4
-----------------------

Method 4 run 1 time: 4 seconds
Method 4 run 2 time: 3 seconds
Method 4 run 3 time: 5 seconds
Method 4 run 4 time: 4 seconds
Method 4 run 5 time: 4 seconds
Method 4 total time: 20 seconds
Method 4 average time: 4 seconds

有趣的是,在Windows 7 x64上使用功能更强大的硬件执行批处理文件比在Windows XP x86上花费更多的时间.但是对我来说,更有趣的是,方法2比方法1快5.86倍,这仅仅是因为使用了 FOR 而不是 GOTO 循环.

为完整起见,第四次运行与第三次运行在同一台计算机上的结果,与在充满电的电池上运行PC的区别在于:

Test runs with method 1
-----------------------

Method 1 run 1 time: 97 seconds
Method 1 run 2 time: 91 seconds
Method 1 run 3 time: 90 seconds
Method 1 run 4 time: 81 seconds
Method 1 run 5 time: 77 seconds
Method 1 total time: 436 seconds
Method 1 average time: 87 seconds

Test runs with method 2
-----------------------

Method 2 run 1 time: 12 seconds
Method 2 run 2 time: 16 seconds
Method 2 run 3 time: 17 seconds
Method 2 run 4 time: 16 seconds
Method 2 run 5 time: 13 seconds
Method 2 total time: 74 seconds
Method 2 average time: 14 seconds

Test runs with method 3
-----------------------

Method 3 run 1 time: 6 seconds
Method 3 run 2 time: 6 seconds
Method 3 run 3 time: 5 seconds
Method 3 run 4 time: 5 seconds
Method 3 run 5 time: 5 seconds
Method 3 total time: 27 seconds
Method 3 average time: 5 seconds

Test runs with method 4
-----------------------

Method 4 run 1 time: 4 seconds
Method 4 run 2 time: 4 seconds
Method 4 run 3 time: 5 seconds
Method 4 run 4 time: 4 seconds
Method 4 run 5 time: 4 seconds
Method 4 total time: 21 seconds
Method 4 average time: 4 seconds

与插入电源的第三次运行相比,方法3到4的执行时间再次没有太大差异.但是方法1的执行时间增加了大约5秒,因此方法1是6.21倍比方法2慢

我真的会对为什么方法1比方法2慢得多并且还取决于电源的种类感兴趣.

由于Windows文件缓存,在所有测试运行中,硬盘活动指示灯仅很少闪烁.

解决方案

根据解释器的此分析, FOR变量将在阶段4中扩展,因此解释器将知道执行该命令多少次以及立即确定哪些值.相比之下,每个GOTO都会在第7阶段进行解释,因此每次都需要重新扫描文件以查找标签,这就是感觉到的时差的原因.

I wrote a small batch file to convert a file containing eight 16 bit hexadecimal values per line into a CSV file with the eight values in decimal.

The input data file was the captured output of ADC values of an embedded device sent in packets of eight hexadecimal values in ASCII with carriage return plus line-feed via RS-232 to PC and simply captured on PC into a file. One line in input data file was something like:

000A002D0044008B0125018C01F40237

The CSV file for this line was:

10,45,68,139,293,396,500,567

The batch file worked, but it took several minutes to complete the conversion which shocked me. I expected that Windows command processor takes some seconds for this task which a console application written in C or C++ could to in some milliseconds. But an execution time of several minutes for a data file with less than 512 KiB was definitely not expected by me.

So I looked further on this issue with creating a batch file using four different methods to create a CSV file with decimal values from a data file with hexadecimal values.

The complete batch file for testing the four methods is appended below as well as my test results.

I understand that the first two methods using a subroutine are much slower than the last two methods doing the conversion in one loop with output each CSV line into file on each loop iteration respectively once at end of FOR loop because of calling a subroutine causes several additional steps done by cmd.exe which altogether take a lot of time on doing subroutine calling thousands of times.

But I do not really understand why first method using a GOTO loop is about six times slower than FOR loop with nearly the same two command lines.

Batch file code of method 1:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "DelDataFile="
set "DataFile=%TEMP%\HexValues.dat"
if not exist "%DataFile%" set "DelDataFile=1" & echo 000A002D0044008B0125018C01F40237>"%DataFile%"

for /F "usebackq delims=" %%I in ("%DataFile%") do call :ConvertLine "%%I"

if defined DelDataFile del "%DataFile%"
endlocal
goto :EOF

:ConvertLine
set "DataLine=%~1"
set "AllValues="
set "StartColumn=0"
:NextValue
set /A Value=0x!DataLine:~%StartColumn%,4!
set "AllValues=%AllValues%,%Value%"
set /A StartColumn+=4
if not %StartColumn% == 32 goto NextValue
echo %AllValues:~1%
goto :EOF

Batch file code of method 2:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "DelDataFile="
set "DataFile=%TEMP%\HexValues.dat"
if not exist "%DataFile%" set "DelDataFile=1" & echo 000A002D0044008B0125018C01F40237>"%DataFile%"

for /F "usebackq delims=" %%I in ("%DataFile%") do call :LineConvert "%%I"

if defined DelDataFile del "%DataFile%"
endlocal
goto :EOF

:LineConvert
set "DataLine=%~1"
set "AllValues="
for /L %%J in (0,4,28) do (
    set /A Value=0x!DataLine:~%%J,4!
    set "AllValues=!AllValues!,!Value!"
)
echo !AllValues:~1!
goto :EOF

And I discovered additionally on running tests to find out the reason by myself that method 1 takes 5 to 10 seconds longer on PC running on battery than on power supply being plugged in.

The question:

What is the reason for much slower execution of the GOTO loop used by method 1 in comparison to the FOR loop used by method 2 and why does method 1 depend on kind of power supply of PC?


Here is the entire batch file being used to compare the different methods:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
cls
set "TestRuns=5"
set "DelDataFile="
set "DataFile=%TEMP%\HexValues.dat"
if exist "%DataFile%" goto InitMethod1

set "DelDataFile=1"
echo Creating data file which takes some seconds, please wait ...
setlocal
set "HexDigits=0123456789ABCDEF"
set "DataLine="
(for /L %%I in (0,1,32767) do (
    set /A "Digit1=(%%I >> 12) %% 16"
    set /A "Digit2=(%%I >> 8) %% 16"
    set /A "Digit3=(%%I >> 4) %% 16"
    set /A "Digit4=%%I %% 16"
    set "HexValue="
    for %%J in (!Digit1! !Digit2! !Digit3! !Digit4!) do set "HexValue=!HexValue!!HexDigits:~%%J,1!"
    set "DataLine=!DataLine!!HexValue!"
    set /A "ValuesPerLine=%%I %% 8"
    if !ValuesPerLine! == 7 (
        echo !DataLine!
        set "DataLine="
    )
))>"%DataFile%"
endlocal
echo/


:InitMethod1
call :MethodInit 1
:RunMethod1
set /A TestRun+=1
set "CSV_File=%TEMP%\Values%Method%_%TestRun%.csv"
del "%CSV_File%" 2>nul
call :GetTime StartTime

for /F "usebackq delims=" %%I in ("%DataFile%") do call :ConvertLine "%%I"

call :OutputTime
if %TestRun% LSS %TestRuns% goto RunMethod1
call :MethodResults
goto InitMethod2

:ConvertLine
set "DataLine=%~1"
set "AllValues="
set "StartColumn=0"
:NextValue
set /A Value=0x!DataLine:~%StartColumn%,4!
set "AllValues=%AllValues%,%Value%"
set /A StartColumn+=4
if not %StartColumn% == 32 goto NextValue
>>"%CSV_File%" echo %AllValues:~1%
goto :EOF


:InitMethod2
call :MethodInit 2
:RunMethod2
set /A TestRun+=1
set "CSV_File=%TEMP%\Values%Method%_%TestRun%.csv"
del "%CSV_File%" 2>nul
call :GetTime StartTime

for /F "usebackq delims=" %%I in ("%DataFile%") do call :LineConvert "%%I"

call :OutputTime
if %TestRun% LSS %TestRuns% goto RunMethod2
call :MethodResults
goto InitMethod3

:LineConvert
set "DataLine=%~1"
set "AllValues="
for /L %%J in (0,4,28) do (
    set /A Value=0x!DataLine:~%%J,4!
    set "AllValues=!AllValues!,!Value!"
)
echo !AllValues:~1!>>"%CSV_File%"
goto :EOF


:InitMethod3
call :MethodInit 3
:RunMethod3
set /A TestRun+=1
set "CSV_File=%TEMP%\Values%Method%_%TestRun%.csv"
del "%CSV_File%" 2>nul
call :GetTime StartTime

for /F "usebackq delims=" %%I in ("%DataFile%") do (
    set "DataLine=%%I"
    set "AllValues="
    for /L %%J in (0,4,28) do (
        set /A Value=0x!DataLine:~%%J,4!
        set "AllValues=!AllValues!,!Value!"
    )
    echo !AllValues:~1!>>"%CSV_File%"
)

call :OutputTime
if %TestRun% LSS %TestRuns% goto RunMethod3
call :MethodResults
goto InitMethod4


:InitMethod4
call :MethodInit 4
:RunMethod4
set /A TestRun+=1
set "CSV_File=%TEMP%\Values%Method%_%TestRun%.csv"
del "%CSV_File%" 2>nul
call :GetTime StartTime

(for /F "usebackq delims=" %%I in ("%DataFile%") do (
    set "DataLine=%%I"
    set "AllValues="
    for /L %%J in (0,4,28) do (
        set /A Value=0x!DataLine:~%%J,4!
        set "AllValues=!AllValues!,!Value!"
    )
    echo !AllValues:~1!
))>>"%CSV_File%"

call :OutputTime
if %TestRun% LSS %TestRuns% goto RunMethod4
call :MethodResults
goto EndBatch


:GetTime
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "%1=%%I"
goto :EOF

:MethodInit
set "Method=%1"
echo Test runs with method %Method%
echo -----------------------
echo/
set "TestRun=0"
set "TotalTime=0"
goto :EOF

:MethodResults
set /A AverageTime=TotalTime / TestRun
echo Method %Method% total time: %TotalTime% seconds
echo Method %Method% average time: %AverageTime% seconds
echo/
goto :EOF

:OutputTime
call :GetTime EndTime
set /A StartTime=(1%StartTime:~8,2% - 100) * 3600 + (1%StartTime:~10,2% - 100) * 60 + 1%StartTime:~12,2% - 100
set /A EndTime=(1%EndTime:~8,2% - 100) * 3600 + (1%EndTime:~10,2% - 100) * 60 + 1%EndTime:~12,2% - 100
set /A DiffTime=EndTime - StartTime
set /A TotalTime+=DiffTime
echo Method %Method% run %TestRun% time: %DiffTime% seconds
goto :EOF


:EndBatch
if defined DelDataFile del "%DataFile%"
del /Q "%TEMP%\Values?_*.csv"
endlocal

It creates first the data file with incrementing hexadecimal values in folder for temporary files which take already some seconds. Please comment the antepenultimate command line of this batch file to keep that file in case of running this batch file multiple times or being interested in this file.

Then it runs five times the four methods for reading the hexadecimal values from data file and writing the values in decimal into a CSV file with printing the test results to console respectively handle STDOUT.

Finally it deletes all CSV files created also in folder for temporary files all having same content. Please comment last but one command line to keep those CSV files on being interested in those files.

This batch file was executed by me four times on two notebooks.

Here are the results of first run on a notebook with an Intel Core Duo P8400 with 2.26 GHz and 2 GiB RAM with a HDD with 7200 rpm running Windows XP x86 with power supply plugged in:

Test runs with method 1
-----------------------

Method 1 run 1 time: 51 seconds
Method 1 run 2 time: 51 seconds
Method 1 run 3 time: 51 seconds
Method 1 run 4 time: 52 seconds
Method 1 run 5 time: 51 seconds
Method 1 total time: 256 seconds
Method 1 average time: 51 seconds

Test runs with method 2
-----------------------

Method 2 run 1 time: 9 seconds
Method 2 run 2 time: 9 seconds
Method 2 run 3 time: 9 seconds
Method 2 run 4 time: 8 seconds
Method 2 run 5 time: 9 seconds
Method 2 total time: 44 seconds
Method 2 average time: 9 seconds

Test runs with method 3
-----------------------

Method 3 run 1 time: 3 seconds
Method 3 run 2 time: 3 seconds
Method 3 run 3 time: 4 seconds
Method 3 run 4 time: 3 seconds
Method 3 run 5 time: 3 seconds
Method 3 total time: 16 seconds
Method 3 average time: 3 seconds

Test runs with method 4
-----------------------

Method 4 run 1 time: 3 seconds
Method 4 run 2 time: 2 seconds
Method 4 run 3 time: 2 seconds
Method 4 run 4 time: 2 seconds
Method 4 run 5 time: 2 seconds
Method 4 total time: 11 seconds
Method 4 average time: 2 seconds

Method 2 is 5.67 times faster than method 1. Method 3 and 4 are even faster than method 2, but that is expected by me. Most of the 2 and 3 seconds needed by methods 3 and 4 are from WMIC command to get local date and time in region independent format.

Here are the results of second run on same computer as first run with the difference on running the PC on full charged battery:

Test runs with method 1
-----------------------

Method 1 run 1 time: 63 seconds
Method 1 run 2 time: 61 seconds
Method 1 run 3 time: 61 seconds
Method 1 run 4 time: 61 seconds
Method 1 run 5 time: 61 seconds
Method 1 total time: 307 seconds
Method 1 average time: 61 seconds

Test runs with method 2
-----------------------

Method 2 run 1 time: 11 seconds
Method 2 run 2 time: 10 seconds
Method 2 run 3 time: 10 seconds
Method 2 run 4 time: 10 seconds
Method 2 run 5 time: 10 seconds
Method 2 total time: 51 seconds
Method 2 average time: 10 seconds

Test runs with method 3
-----------------------

Method 3 run 1 time: 3 seconds
Method 3 run 2 time: 4 seconds
Method 3 run 3 time: 3 seconds
Method 3 run 4 time: 4 seconds
Method 3 run 5 time: 3 seconds
Method 3 total time: 17 seconds
Method 3 average time: 3 seconds

Test runs with method 4
-----------------------

Method 4 run 1 time: 2 seconds
Method 4 run 2 time: 2 seconds
Method 4 run 3 time: 2 seconds
Method 4 run 4 time: 2 seconds
Method 4 run 5 time: 2 seconds
Method 4 total time: 10 seconds
Method 4 average time: 2 seconds

It can be seen that for methods 2 to 4 the processing times increase just a little bit. But processing time of method 1 increases by 10 seconds and so this solution is now about 6.10 times slower than method 2. I have no idea why processing time of method 1 depends on kind of power supply.

Here are the results of first run on a notebook with an Intel Core Duo T9600 with 2.80 GHz and 4 GiB RAM with an SSD running Windows 7 x64 with power supply plugged in:

Test runs with method 1
-----------------------

Method 1 run 1 time: 91 seconds
Method 1 run 2 time: 88 seconds
Method 1 run 3 time: 77 seconds
Method 1 run 4 time: 77 seconds
Method 1 run 5 time: 78 seconds
Method 1 total time: 411 seconds
Method 1 average time: 82 seconds

Test runs with method 2
-----------------------

Method 2 run 1 time: 11 seconds
Method 2 run 2 time: 16 seconds
Method 2 run 3 time: 16 seconds
Method 2 run 4 time: 14 seconds
Method 2 run 5 time: 16 seconds
Method 2 total time: 73 seconds
Method 2 average time: 14 seconds

Test runs with method 3
-----------------------

Method 3 run 1 time: 6 seconds
Method 3 run 2 time: 4 seconds
Method 3 run 3 time: 4 seconds
Method 3 run 4 time: 4 seconds
Method 3 run 5 time: 6 seconds
Method 3 total time: 24 seconds
Method 3 average time: 4 seconds

Test runs with method 4
-----------------------

Method 4 run 1 time: 4 seconds
Method 4 run 2 time: 3 seconds
Method 4 run 3 time: 5 seconds
Method 4 run 4 time: 4 seconds
Method 4 run 5 time: 4 seconds
Method 4 total time: 20 seconds
Method 4 average time: 4 seconds

It was interesting to see that the batch file execution with more powerful hardware takes more time on Windows 7 x64 than on Windows XP x86. But even more interesting for me is again the fact that method 2 is 5.86 times faster than method 1 just because of using a FOR instead of a GOTO loop.

For completeness the results of fourth run on same computer as third run with the difference on running the PC on full charged battery:

Test runs with method 1
-----------------------

Method 1 run 1 time: 97 seconds
Method 1 run 2 time: 91 seconds
Method 1 run 3 time: 90 seconds
Method 1 run 4 time: 81 seconds
Method 1 run 5 time: 77 seconds
Method 1 total time: 436 seconds
Method 1 average time: 87 seconds

Test runs with method 2
-----------------------

Method 2 run 1 time: 12 seconds
Method 2 run 2 time: 16 seconds
Method 2 run 3 time: 17 seconds
Method 2 run 4 time: 16 seconds
Method 2 run 5 time: 13 seconds
Method 2 total time: 74 seconds
Method 2 average time: 14 seconds

Test runs with method 3
-----------------------

Method 3 run 1 time: 6 seconds
Method 3 run 2 time: 6 seconds
Method 3 run 3 time: 5 seconds
Method 3 run 4 time: 5 seconds
Method 3 run 5 time: 5 seconds
Method 3 total time: 27 seconds
Method 3 average time: 5 seconds

Test runs with method 4
-----------------------

Method 4 run 1 time: 4 seconds
Method 4 run 2 time: 4 seconds
Method 4 run 3 time: 5 seconds
Method 4 run 4 time: 4 seconds
Method 4 run 5 time: 4 seconds
Method 4 total time: 21 seconds
Method 4 average time: 4 seconds

There is again not much difference in execution time for the methods 3 to 4 in comparison to third run with power supply plugged in. But the execution time of method 1 increases by approximately 5 seconds and for that reason method 1 is 6.21 times slower than method 2.

I would be really interested in why method 1 is so much slower than method 2 and additionally depends on kind of power supply.

The hard disk activity LED was only very rarely blinking on all test runs as expected by me because of Windows file caching.

解决方案

According to this analysis of the interpreter, the FOR variable will be expanded in phase 4, so the interpreter will know how many times to execute the command and on what values immediately. In contrast, each GOTO is interpreted in phase 7, and it requires scanning the file anew looking for the label each time, which accounts for the perceived time difference.

这篇关于为什么GOTO循环比FOR循环慢得多,并且还取决于电源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆