ハンドル投げとオブジェクト PowerShell get-content の遅さと Forea | ブログのタイトルを入力します。

ハンドル投げとオブジェクト PowerShell get-content の遅さと Forea

ハンドル投げとオブジェクト PowerShell get-content の遅さと Foreach-Object の妙な使い方。

PowerShell のバージョンは、2 の話。

オブジェクトをパイプするらしいが、PowerShell はテキスト処理が重く遅すぎる。
特に配列の追加が遅い。

get-content は、ファイルを読むときファイルの行数、で妙な動きをする。

場合わけすると、
 イ:サイズが0 (0行)
 ロ:1行
 ハ:2行以上
 ニ:大量行

で、最速かつ 0行、1行の対応を行う方法を考えてみた。
Foreach-Object を使う必要はないと思うけど、ワンライナー風にしてみた。

get-content .\50万行.txt -readcount 0 | Foreach-Object -Begin {$xxx=@()} -Process {$xxx=$_}

これが、0行、1行、2行以上で最速かつメモリーの消費量がもっとも少なかった。
そして、ワンライナー風

0行のときは、$xxx.count は、0 <=== -Begin が効いている。
1行のときは、$xxx.count は、1 <=== -readcount 0 が効いている。
になる。
そして、早い。 <=== -readcount 0 が効いている。

デフォルトのreadcount 1 は、1行づつパイプするらしい。
バッファリングはしていると思うが。
遅い。
readcount 1 だと、1万行程度で数十分かかるんじゃないかな。
動かすマシンのパワーによるだろうけど。

get-content は、ファイルが1行のとき、[string]になってしまう。
しかも、$xxx.count は、 何故か0 だ。
非常に都合が悪い。最悪だ。

更に、get-contentは、0行ファイルのとき、スルーする。
これは、非常に都合が悪い。

get-content の後に、色々やることがある場合は、
-readcount 0 だ。
でも、パイプの意味がなくなる。

-readcount 1だと、散々メモリを消費して、最後に解放するが、
その解放されたメモリが他のプロセスで使えるのかどうかは分からない。

PowerShell はメモリを沢山積んでいて、ディスクもメモリ並みに早いマシンじゃないとだめだな。

汎用機で動かしたら便利かもしれない。
が、汎用機にWindows はないな。