人気ブログランキング | 話題のタグを見る
- 北の空からみなみへ -
exblog staff

ping test
2021年 06月 01日
ルーターまでの経路で、やや不安定なスイッチが存在しているようで、無限pingでぶっ叩きつつエラー頻度をトレースするワンライナー

C:\Windows\System32\cmd.exe /k "echo ping test from %time%&set $count$=&set $total$=&for /l %i in (1,0,1) do @set/a $total$+=1 >nul&ping -n 1 -w 10 192.168.0.1|find "100%">nul&&(set/a $count$+=1&cmd/v/c echo+ 回目 / !$total$! 回中 のping失敗 @ %time% - !time!)"
# by bucmacoto | 2021-06-01 14:50 | &Tips;&code;
実用的ワンライナー(スタートアップのOUTLOOK起動時に一定時間のWaitを入れる)
2018年 04月 04日
Windows 10 の sturtupで OUTLOOKを起動時に自動起動していたのだが、このところコケまくり。
そこで20秒ほどの待ちを入れてみた。
C:\Windows\System32\cmd.exe /c"timeout.exe 20&start "" "C:\Program Files\Microsoft Office 15\root\office15\outlook.exe" /cleanreminders"

引用符の入れ子っぽいが、ちゃんと動く。ショートカットに書くならワンライナーだと思う。(バッチとするほどじゃない)
/cleanreminders は OUTLOOK起動時にリマインダーアラームを初期化(音を停止)するオプション。
# by bucmacoto | 2018-04-04 20:29 | &Tips;&code;
1 line FizzBuzz benchmark
2018年 03月 19日

1行FizzBuzzの千回ループベンチを、仕事終わりの帰りがけに最遅のマシンにもう一度走らせてみた。
すると、(うっかり表示を垂れ流したとはいえ)140msという遅さを叩き出した。
そういえば、Celeronのこのマシンと、core i3の2台には、Microsoft Office がインストール済みだった。
いかにも疑わしい。これは再確認しておきたい。

それとともに、マシンの違いによる速度差と、コードの中身でのそれとを比較したくて、最初コード最後のものとでベンチをやり直してみました。
まさかofficeをアンインストールするわけにもいかず、前回ベンチを取った時と同じく再起動しての実行です。

やっている途中で速度がばらつき、出力をnulにしないで表示をさせてみると、たまにひっかかっている感じになりました。
あれ?これって、もしかしたらバックグラウンドプロセスの影響かな?
そこでネットから切り離して、Defenderのリアルタイム監視をを停止したら、速度は上がりました。

そういえば、業務側は最小限のウイルス対策で済むよう物理的に外部と切り離し、セキュアに保っていたのでした。(アンチウイルスソフトは入っているが、当初稼働のtm社はオーバーヘッド大きすぎて、より軽いm社のものだし、いまではサポート切れでサーバのウイルスデータベースの更新も停止)
そういう意味では、前回取得していたのはマシン性能よりもバックグラウンド負荷のベンチマークだった。こう言えるかも知れない。

んでやってみたけっかはっぴょう。旧コード(文字変数逐次書き換え版)の出力on と off、最終コード(計算分岐最小限のリスト展開版)で 出力off と on です。
1 line FizzBuzz benchmark_c0062295_20245588.gif

ふむふむ。表示のON/OFFでは、8~9ms程度の差。数文字x百行程度の文字出力では、負荷のほうはそれほどではない。
けれども、コード差では3倍の速度差。。
やはり除算(剰余)はプログラムの速度低下の要素なのですね。
(IF文もそうらしいが、このコードでその差は大きくない。むしろ変数の部分書き換え多用が元凶か。)

あとでまたやり直したくなった時に、効率的にできるように手順をメモ


最初に、CMD/v:on でコマンドプロンプトを起動(具体的には次のコマンド入力)
color f0&cmd/v:on/k"prompt $g &title Celeron G1620 2.7GHz"

回数をセット
set $count=1000

次に新旧FizzBuzzのコード引数を、変数FizzBuzzとして代入

こちら新の方
set FizzBuzz="for /L %a in (0,1,6) do for %A in (1 2 Fi 4 Bu Fi 7 8 Fi Bu 11 Fi 13 14 FizzBu) do if %a11==6%A (exit) else if %A gtr a (echo.%Azz) else set/a $=15*%a+%A&echo."
こちら旧のほう
set FizzBuzz="for /L %A in (1,1,100) do (set/a I=%A%3,Z=%A%5>nul&(for %B in (!I!) do set I=!I:~%B,1!)&for %B in (!Z!) do set Z=!Z:~%B,1!)&set $= &(if defined I set $=!$!Fizz)&(if defined Z set $=!$!Buzz)&set $=!$:~1!&(if not defined $ set $=%A)&echo !$!"

ベンチマークを実行 (%FizzBuzz% 直後の閉じカッコ直後に >nul を出し入れて表示を on/off)
(for /L %z in (1,1,!$count!) do cmd/q/v:on/c%FizzBuzz%)>nul&set etime=!time!&set/p<nul=%time%-!etime!/!$count!Loop Average = &set/a ltime=((1000*(3600*!etime:~0,2!+60*(1!etime:~3,2!-100)+1!etime:~6,2!-100)+1!etime:~-2!0-1000-(1000*(3600*%time:~0,2%+60*(1%time:~3,2%-100)+1%time:~6,2%-100)+1%time:~-2%0-1000))+86400000)%86400000/!$count!&echo ms


more
# by bucmacoto | 2018-03-19 02:49 | quote/data
コマンドプロンプトの1行ベンチマーク
2018年 03月 11日
先の1行FizzBuzzを反復実行して、所要時間から処理速度を判別しようとしたら、老化脳では「どのくらい?」という程度感覚が掴めなかった。
(また、処理出力をNULリダイレクトで隠してしまえばいいが、表示させてしまうと、100行×1000試行=10万行の彼方に開始時刻が流れ去っていて確認に困った)

なので、一行FizzBuzzの反復試行ルーチンのさらに前後に手を入れて、開始時間を表示し→計算反復の実行→終了時間を表示し所要時間を表示する。ように書き加えてみた。
(例によって後で再度使い回す場合のために、備忘録として記録)

説明文を簡便化するために、実行する本体を仮に FIZZBUZZとおこう(代入だね)。

実行土台となる CMD.EXE は、スイッチ /v:on で遅延変数展開ONでコマンドプロンプトを起動しておく。
(現在時刻変数 time の一行内の時間差から、所要時間を算出するのだから、これは必須。)
このところ、砂場遊びでは次の一行をコマンドプロンプト起動直後に入れるのがルーチン化している。(自動でこうなるようにできるが、それは禁じ手=職場PCなので)

color F0&cmd/v:on/k prompt $g ^&title SandBox

FIZZBUZZの1,000回実行コードはこんな感じ。

for /L %z in (1,1,1000) do FIZZBUZZ
これを画面に表示させずNULへ流すには、括弧で括ってリダイレクトアウト。
(for /L %z in (1,1,1000) do FIZZBUZZ)>nul

この前に現在時刻を取得し、深夜0時からのミリ秒数計算のコードをおく。(バッチ内でない限り、set/a で代入するための計算結果はコンソール表示されてしまうので、まとまるように書く)

バッチ出力を最低限の改行で済ませるために、コードは set/p&nul="改行なし表示出力" の形式を多用。
投稿ボックス内で自動改行されると空白などが分かりにくいから横長表示で。
(ついでにマウスオン解説表示も多用)
この上には表示や計算結果や解説が表示されます。
set/p&nul=start=%tilme%[
start= 01:23:45.67[5025670]
set/p&nul=start=%tilme%[
&set stime=%time%
変数 stime(=start time) に時刻を代入(※実のところ1行処理なら無用=後で解説)
set stime=%time%
&set/a start
変数 start にミリ秒変換した開始時刻を代入(表示もされる)
set/a start
=1000*(!stime:~0,2!*3600+(1!stime:~3;2!-100)60+(1!stime:~6,2!-100)
start= 01:23:45.67[5025670] "時刻文字列"を秒数に
!stime:~0,2!*3600+(1!stime:~3;2!-100)60+(1!stime:~6,2!-100)
)+1!stime:~-2!0-1000
start= 01:23:45.67[5025670]
+1!stime:~-2!0-1000
&echo.]
start= 01:23:45.67[5025670]
echo.]
&

後半もほとんど同じコードですね。
この上には表示や計算結果や解説が表示されます。
&set etime=!time!
変数 etime(=end time) に時刻を代入完了「直後」の時刻
set etime=!time!
&set/p&nul=end=!etime![
start= 02:08:45.67[7725670] average=270ms
set/p&nul=end=!etime![
&set/a end
変数 end にミリ秒変換した処理完了時刻を代入(表示もされる)
set/a end
=1000*(!etime:~0,2!*3600+(1!etime:~3;2!-100)60+(1!etime:~6,2!-100)
end= 02:08:45.67[[7725670] average=270ms "時刻文字列"を秒数に
!etime:~0,2!*3600+(1!etime:~3;2!-100)60+(1!etime:~6,2!-100)
)+1!etime:~-2!0-1000
end= 02:08:45.67[7725670] average=270ms
+1!etime:~-2!0-1000
&set/p&nul=] average=
end= 02:08:45.67[7725670] average=270ms
set/p&nul=] average=
&anp;set/a ltime=(!end!-!start!)/1000
end= 02:08:45.67[7725670] average=270ms(計算結果は改行なしで表示される)
set/a ltime=(!end!-!start!)/1000
&echo.ms
end= 02:08:45.67[7725670] average=270ms
echo.ms

あとは、前半コード+FIZZBUZZコード+後半コード のサンドイッチで出来上がり。
ということで職場で私が触れる範囲のPCやWSでベンチマークを実行してみました。(結果はmore欄で)

ですが、この投稿にまとめていて気づいたのです。
遅延変数展開下の環境では、変数参照に !変数!(遅延展開=実行時に動的変数として展開)と %変数%(時即時展開=コマンドライン改行の瞬間に一行内の変数は確定)とが、「どちらも」使えるのでした。

つまり、サンドイッチに挟まなくても、
(処理) & (終了時刻「!time!」・開始時刻「%time%」で所要計算)
みたいにすれば、より簡明な記述ができたのですね。。。。orz...

さらにループ回数を柔軟に設定できるように書き換えると、こうなります。
(実地検証でこけまして修正)
(if not defined $count set/a $count=1000)&(for /L %z in (1,1,!$count!) do FIZZBUZZ)>nul&set etime=!time!&set/p<nul=%time%-!etime!/!$count!Loop Average = &set/a ltime=(1000*(3600*!etime:~0,2!+60*(1!etime:~3,2!-100)+1!etime:~6,2!-100)+1!etime:~-2!0-1000-(1000*(3600*%time:~0,2%+60*(1%time:~3,2%-100)+1%time:~6,2%-100)+1%time:~-2%0-1000))/!$count!&echo ms
1日を跨ぐ場合には、ltime が負数になるので、86400000を加え86400000で剰余を取るなどして正数化したミリ秒数を 試行回数 $countで割る。このように扱う必要もあるけど、そこまで使うケースはおそらくない。
(if not defined $count set/a $count=1000)&(for /L %z in (1,1,!$count!) do cmd/q/v:on/c"for /L %a in (0,1,6) do for %A in (1 2 Fi 4 Bu Fi 7 8 Fi Bu 11 Fi 13 14 FizzBu) do if %a11==6%A (exit) else if %A gtr a (echo.%Azz) else set/a $=15*%a+%A&echo.")&set etime=!time!&set/p<nul=%time%-!etime!/!$count!Loop Average = &set/a ltime=((1000*(3600*!etime:~0,2!+60*(1!etime:~3,2!-100)+1!etime:~6,2!-100)+1!etime:~-2!0-1000-(1000*(3600*%time:~0,2%+60*(1%time:~3,2%-100)+1%time:~6,2%-100)+1%time:~-2%0-1000))+86400000)%86400000/!$count!&echo ms


じっこうけっか と 小さな説
# by bucmacoto | 2018-03-11 22:09 | &Tips;&code;
砂場遊び(1行FizzBuzz)/後片付け
2018年 03月 08日
砂場遊び(1行FizzBuzz)

bugmacotoとも言うべきお間抜けコードを前投稿(more欄)で晒した。Windows実機でちゃんと動くコードに直したので再掲する。
なお、ちょこっとずつ解説入れておこう。(自分でも後から可読する自信はないらしい)

まずは、最短(なんちゃってなので105までカウントアップが突っ走り)なBizzBuzz方言版

cmd/q/v:on/c "for /L %a in (0,1,6) do for %A in (1 2 i 4 u i 7 8 i u B i D E izzBu) do if %A gtr f (echo.B%Azz) else set/a $=15*%a+0x%A&echo."
142 ↑ byte
    cmdのオプション
  • /q : echo off状態で起動
  • /v:on : 変数の遅延展開を有効にした状態で起動
    バッチで SETLOCAL ENABLEEXTENSIONS 宣言下と同じ状態
  • /c : 残り全部を引用符で囲まれたパラメータ(引数)を続けると、最初と最後の引用符が外されてコマンドライン上で実行される感じになる。
    (マイクロソフトのcmd.exeの文字列を扱う実装は、ちょっとずつ状況に応じて変化する=一貫性はない感じ。
     BASIC時代から、対称性の破れみたいな実装を好んでいる感じがする。)
    遅延展開有効下での例 : 比較文字として キャレットで「|」と引用符「"」を比較
    引用符にキャレットって無効では?(なんと有効でした。むしろ \" なんて書くとエラーします)

    > if ^| gtr ^" echo !time: =0!
    20:00:00.00

    > if ^| gtr ^" echo.!time: =0!
    !time: =0!

    echoの後ろに、空白区切りとピリオド区切りとで、変数の拡張展開されたり、されずにそのまま文字列表示になったり。

次に16進アイデアを温存したままで、方言ではないFizzBuzzへの対応版
無理やりな文字列比較をして動くようになったバージョン
なお、16進コードの A~F は大文字でも小文字でもいいらしい。
さらには、引用符あっても(0x"F" と書くとそれは 15 になる)OKという実装。

cmd/q/v:on/c "for /L %a in (0,1,6) do for %A in (1 2 Fi 4 Bu Fi 7 8 Fi Bu "b" Fi "d" "e" FizzBu) do if %A gtr "f" (echo.%Azz) else set/a $=15*%a+0x%A&echo."
156 ↑ byte
    if での比較は、記号 < 数字 < 文字
    (同じ文字なら大文字が大きいが、大文字の A は小文字の b より小さいという定義 )
  • 例 :
    >if b gtr A echo
    ECHO は <ON> です。
  • set/a での変数へ代入する計算結果はバッチ内では結果は表示されないが、コマンドライン上では表示される。
    なお、改行はされない。
    (echo ではなく set/p<nul= で出力したのと同様な吐き出し方をしてる)
  • set/a $= : $は仮変数(ダミー)
    昨日の寝ぼけた式は間違いで、こちらがちゃんとしたカウントアップ。
  • &echo. : 数値は吐き出されても改行はされていない。なので空改行を入れている
    (echo だけでは 「ECHO は <ON> です。」が出るのはおなじみ)

文字比較式があんまりなので、16進数のアイデアを放棄したらむしろ短くなった。
これでかなりすっきりして、分かりやすくなった。

cmd/q/v:on/c "for /L %a in (0,1,6) do for %A in (1 2 Fi 4 Bu Fi 7 8 Fi Bu 11 Fi 13 14 FizzBu) do if %A gtr a (echo.%Azz) else set/a $=15*%a+%A&echo."
149 ↑ byte
  • >ここでは、gtr で 最小の英文字 a と文字比較している。
    より一般的にするなら、if %A geq a とすることで、変数%Aに代入された全ての文字(記号と数字以外)が処理対象となる。
    結果、else 以降は数字処理に専念となる。
  • %A=Fi : 後ろに zz で Fizz
  • %A=Bu : 後ろに zz で Buzz
  • %A=FizzBu : 後ろに zz で FizzBuzz

最後に仕上げ。

FizzBuzz問題は、1から100 という条件なので、それに対応する IF文を加える。
cmdの /c スイッチに続くのが引用符つきのパラメータの場合は、直後の空白を削っても正しく解釈されるのでそうした。

cmd/q/v:on/c"for /L %a in (0,1,6) do for %A in (1 2 Fi 4 Bu Fi 7 8 Fi Bu 11 Fi 13 14 FizzBu) do if %a11==6%A (exit) else if %A gtr a (echo.%Azz) else set/a $=15*%a+%A&echo."
173 ↑ byte
    遅延変数展開下とはいっても、%変数%の形式はしっかり有効なまま。
    (改行するまでは、展開=反映されない変数として普通の環境同様に扱われる)
  • if %a11==6%A (exit) ← これはOK
  • if %a%A==611 (exit) ← これNG
  • ※ なぜなら %a% という変数展開を優先されてしまうので 下の例では
    「%a%A」という4文字を 611 と比較する式に解釈される。
    そこで、たすき掛けにしてやるとまともに動いた。


(more欄のスクリーンショットは撤廃)→ 反復実行の前後時間から平均所要時間を算定の 1行ベンチマークテスト については次の投稿で。
# by bucmacoto | 2018-03-08 21:13 | &Tips;&code;