.bat（バッチファイル）の、頻出コマンドの所要時間について

#前提
　バッチファイルでは、行うバッチ処理の**対象が広くなれば広くなるほど処理にかかる時間が増していきます。**
　対象が１台のPCと１００台のPCでは後者の方が多くの時間を必要とするのは自明ですね。
　そこで少しでもバッチファイルの実行時間を短くするために、**ループ処理**にかかる
時間を計測し、考察します。

#計測する処理の対象
　batでループ処理をする方法は、
①変数の値を増加・減少させながら**同じラベルを複数回実行する「goto」**
②特定の変数の値の範囲を設定し、その**条件を満たしている限り後続の処理を実行する「for」**
　が挙げられます。

　今回は比較の対象として次の４つの構文を用います。
　いずれも**2500個の変数に1を代入するもの**です。
　配列表記していますが、この配列はBASE1（要素の先頭が[1]）です。
　[50][50]及び[2500]をforとgotoでそれぞれ設定する４通りです。


##対象①：一次元配列goto
```bat:①goto[2500]
:GT1
set n1=0
:GT1_1
set /a n1+=1
if %n1% == 2501 exit /b
set num[%n1%]=1
goto GT1_1
```

##対象②：二次元配列goto
```bat:②goto[50][50]
:GT2
set n1=0
:GT2_1
set /a n1+=1,n2=0
if %n1% == 51 exit /b
:GT2_2
set /a n2+=1,n3=0
if %n2% == 51 goto GT2_1
set num[%n1%][%n2%]=1
goto GT2_2
```

##対象③：一次元配列for
```bat:③for[2500]
:F1
for /l %%i in (1,1,2500) do set num[%%i]=1
exit /b
```

##対象④：二次元配列for
```bat:④for[50][50]
:F2
for /l %%i in (1,1,50) do for /l %%j in (1,1,50) do set num[%%i][%%j]=1
exit /b
```

#所要時間実測その１：それぞれの処理の時間
　まずは、単体の時間を計ってみます。
　時間の計測にはすべて同じバッチラベルを使用しており、時間はそれぞれ３回測った平均です。

|**処理**|**時間(ミリ秒)**|
|:-----------:|:-----------:|
|**goto[2500]**|**252**|
|**goto[50][50]**|**288**|
|**for[2500]**|**37**|
|**for[50][50]**|**38**|

　・for文は要素数が同じ場合、時間に差異は生じない。（双方36ms～39ms）
　・それに対して、gotoでは同じ要素数にもかかわらず0.3秒という大きい違いがあり、誤差とは判断できない。

　２つのgoto処理の違いを考えると、目に付くのは経過するラベルの数の違い（≒goto数の違い）、処理の回数の違い。
　そこで、２つのgotoが行っている処理の回数をまとめようとしましたが、その前に
　・setで変数を代入した場合とset /a で変数を計算した場合の時間
　・if文の時間
　・goto文の時間
　を調べる必要があります。

#所要時間実測その２：setとset /a
　以下の計算式ををそれぞれ100000回ずつ実行、時間を測定します。

|**処理**|**時間(ミリ秒)**|**時間2500回換算（÷50）**|
|:-----------:|:-----------:|:--:|
|**set n=1**|**269**|**5.4**|
|**set /a n=1**|**302**|**6.0**|
|**set /a n+=1**|**316**|**6.3**|
|**set /a n+=1,m=1**|**416**|**8.3**|
|**set /a n+=1,m+=1**|**415**|**8.3**|

　・代入でも、/aのあるなしでは若干だが時間は変わってくる模様。（上ふたつ）
　・また、/aを使っているならば代入だろうが加算だろうがさほど時間は変わらないようだ。（２，３番目）
　・意外だったのは、２つの変数をまとめて計算する場合。２倍弱の時間がかかるという予想だったが、実際は1.3倍程度に収まった。（３，４番目）
・２つの計算のうち１つを代入にしても時間は変化しなかった。（下ふたつ）

#所要時間実測その３：if
　４種類のif文に対して100000回実行した時間を計測。当然、ifが真になる回数は同じになるようにしています。

|**処理**|**時間(ミリ秒)**|**時間2500回換算（÷40）**|
|:-----------:|:-----------:|:--:|
|**if 変数==定数**|**50**|**1.25**|
|**if 変数==変数**|**50**|**1.25**|
|**if 変数geq定数**|**50**|**1.25**|
|**if 変数geq変数**|**50**|**1.25**|

　あまりにも同じだったので間違っているのかと思った。同じでした。
　せっかくなので、例では使用しない遅延展開についても検証。

|**処理**|**時間(ミリ秒)**|
|:-----------:|:-----------:|
|**if 変数==遅延変数**|**84**|
|**if 遅延変数==遅延変数**|**108**|
　数値の記載はしませんでしたが、遅延と通常変数が前後しても時間は変わりません。

#所要時間実測その４：goto
　if文で同じラベルをループ。ループ回数は可変。
　ifとset /a +=を使用しているので、結果を減算する必要があります。

|**処理**|**時間(ミリ秒)**|
|:-----------:|:-----------:|
|**50ループ**|**2**|
|**250ループ**|**11**|
|**2500ループ**|**109**|
|**25000ループ**|**1148**|

　-7.6して約**101ms**。１回あたりの時間は0.025ms程度です。

#所要時間実測その５：ラベルの読み込み
　次は、再帰ではなく新しいラベルを経由するとき。
　ループの前後にたくさんのダミーのラベルを並べて時間を見ます。

```bat:例：前に100個のダミーラベルを並べる
:a1
:a2
:a3
 :
 :
:a100
:loop
set /a loop+=1
if %loop% leq 2500 goto loop
```

|**処理**|**時間(ミリ秒)**|**基準との差**|**ラベル１個当たり**|
|:-----------:|:-----------:|:-----------:|:-----------:|
|**前に1000個**|**1124**|**995**|**0.99**|
|**前に100個**|**237**|**108**|**1.08**|
|**前に10個**|**144**|**15**|**1.50**|
|**前に1個（基準）**|**129**|
|**後に10個**|**141**|**12**|**1.20**|
|**後に100個**|**228**|**99**|**0.99**|
|**後に1000個**|**1117**|**988**|**0.99**|

　ラベルがループの前後にあることによって生じた差は、**前後関係なく**ラベル１個当たり約1ms。
　前後が関係なく、かつ一定の時間を要するということは、**新しいラベルを読み込むときは、1msかかる**という推測ができます。

#その１の数値を計算
　それを踏まえて、その１で出た疑問を解消するためにgotoの２つの処理回数をまとめてみます。

|**処理**|**n=**|**n+=**|**n+=,m+=**|**if**|**goto**|**ラベル数**|**累計時間（ミリ秒）**|
|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|
|**[2500]**|**2501**|**2501**|**0**|**2501**|**50**|**2**|**252**|
|**[50][50]**|**2501**|**0**|**2601**|**2550**|**2550**|**3**|**288**|
|**差**|**0**|**-2501**|**2601**|**49**|**2500**|**1**|**36**|
|**差（ミリ秒換算）**|**0**|**-6.3**|**8.6**|**0.025≒0**|**100**|**1**|**102.4**|


　
　　　　　　　　　　　　　　　　　**！？**

　36と102.4、その差66.4。誤差だと信じたいですが多分gotoが悪いです。全処理時間のうち99%もgotoだけで占めるわけないんだよなぁ…。
　まあそれでもたった60ms違ったところで感はあるんですが。


#まとめ
①setコマンドは１回あたり約0.0026ms。400回程度で1ms必要になる。
②set /aで１つの変数を計算すると約0.003ms。330回程度で1ms必要になる。
③set /aで２つの変数をまとめて計算すると約0.0041ms。250回程度で1ms必要になる。
④ifは遅延環境変数を使用しなければ、共通して１回0.0005ms。2000回程度で1ms必要になる。
⑤ifで遅延環境変数を使った場合、１つ使うと0.00084ms。通常の1.7倍程度の時間を必要とする。
⑥ifで両辺が遅延だと0.0011ms。通常の2倍程度の時間を必要とする。
⑦gotoは謎挙動過ぎて分からん。**今後の課題。**他の調査結果には影響していないからgotoの調査はなかったことに。