Rakuでwc -lをエミュレートする方法


9

perl 5では、wc -lonelinerを使用してエミュレートできます。

perl -lnE 'END {say $.}' test.txt

この機能をRakuに実装する方法

これを実装しようとすると:

raku -e 'say "test.txt".IO.open.lines.elems'

遅くなり、多くのメモリを使用することが判明

複製のための情報:

$ wget http://eforexcel.com/wp/wp-content/uploads/2017/07/1500000%20Sales%20Records.zip
$ unzip "1500000 Sales Records.zip"
$ mv "1500000 Sales Records.csv" part.txt
$ for i in `seq 1 10`; do cat part.txt >> test.txt ; done
$ du -sh test.txt
1.8G    test.txt

$ time wc -l test.txt
15000000 test.txt

real    0m0,350s
user    0m0,143s
sys     0m0,205s

$ time perl -lnE 'END { say $. }' test.txt
15000001

real    0m1,981s
user    0m1,719s
sys     0m0,256s

$ time raku -e 'say "test.txt".IO.open.lines.elems'
15000001

real    2m51,852s
user    0m25,129s
sys     0m6,378s

# Using swap (maximum uses 2.2G swap):
# Before `raku -e ''`

$ free -m
              total        used        free      shared  buff/cache   available
Mem:          15009        1695       12604         107         708       12917
Swap:          7583           0        7583

# After `raku -e ''`

$ free -m
              total        used        free      shared  buff/cache   available
Mem:          15009         752       13923          72         332       13899
Swap:          7583         779        6804

# Swap not used
$ time raku -ne '++$ andthen END .say' test.txt
15000001

real    1m44,906s
user    2m14,165s
sys     0m0,653s

$ raku -v
This is Rakudo version 2019.11 built on MoarVM version 2019.11
implementing Perl 6.d.

3
タイミング情報と実際の出力wc(ファイルサイズを含める必要があります)を追加できますか?ありがとうございました。
Elizabeth Mattijsen

質問を更新-再現の例を追加
TheAthlete

2
@TheAthlete追加情報をありがとう。これは、今後数年間でパフォーマンスのギャップが確実に解消されると思われるため、歴史的に興味深い[らく] SOになると思われるので、もう少し情報を追加することを検討してください。まず、あなたが最近の落語を使用していることは明らかですが(書いているためraku)、それでもraku -v出力があると良いでしょう。また、現在の提案のタイミングの出力を追加することを検討してください。また、'ascii'より良い時間を生み出すために、今週末にデコーダーへの切り替えを検討する場合もあります。
レイフ

1
サイドノートでは:-l大幅perlのダウンperlのが遅くなるためのフラグと、それは、この場合には有用ではないのです。私のマシンでは、ランダムな行長で約200k行のファイルを削除する-lと、40%改善されます。
ソリン

回答:


8

比較するとかなり遅いと思われるperlが、比較する価値がある1つのオプション:

raku -ne '++$ andthen END .say' test.txt

lコマンドラインオプションは冗長です。

$ 匿名の状態スカラーです。

andthenlhsが定義されていることをテストし、定義されている場合は、その値をトピック($_)として設定してから、そのrhsを評価します。

END似ているperlEND。に戻りますNilが、副作用のために 'ステートメントをandthen使用しているため、ここでは問題になりませんEND

このコードの速度にはいくつかの影響があります。私が考えることができるいくつかのこと:

  • コンパイラの起動オーバーヘッド。使用されているモジュールを無視すると、rakuコンパイラRakudoの起動オーバーヘッドは、のごくわずかなものに比べて、一般的なハードウェアでは約10分の1秒ですperl

  • 「線」の概念。ではperl、行処理のデフォルトの概念は一連のバイトを読み取ることであり、その一部は行末を表します。ではraku、行処理のデフォルトの概念はUTF-8文字列を読み取ることであり、その一部は行末を表します。したがってperl、ASCII(または拡張ASCII)デコーダーの読み取りオーバーヘッドのみが発生しrakuますが、UTF-8デコーダーの読み取りオーバーヘッドは発生します。

  • コンパイラの最適化。 perl一般的に最大に最適化されています。perl -lnE 'END {say $.}' test.txtいくつかの巧妙な最適化を利用したとしても、私は驚かないでしょう。対照的に、楽堂最適化の作業はまだ比較的初期の段階にあります。

上で述べた3つのポイントの最初と最後について誰でもできると私が思う唯一のことは、N年待つか、コンパイラの改善に貢献することです。

rakuのデフォルトのUTF-8を回避する方法があります。おそらく、次のようなものはすでに実行可能で、rakuのデフォルトよりも大幅に高速です。少なくとも、というモジュールを使用するオーバーヘッドを無視しますfoo

raku -Mfoo -ne '++$ andthen END .say' test.txt

ここで、モジュールfooはファイルI / OのデフォルトのエンコーディングをASCIIまたは使用可能なエンコーディングから何かに切り替えます。

これが現在の楽堂で実際に実行可能かどうかは確認していませんが、実行できない場合は驚かれることでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.