Perlでちょっとだけ標準入力を最適化する方法
とりあえず、おさらいから。
でもって、その前にテストデータを用意します。
こんな感じでワンライナーを打つか、コピペしてください。
$ perl -E 'say $_ for 1..10' > data.txt
$ cat data.txt
1
2
3
4
5
6
7
8
9
10
今回から、use v5.10;
は他の方を見習って最初に書くことにしました。
use v5.10; use strict; use warnings; say <>;
こんな感じで実行する。
$ perl aaa.pl < data.txt
1
2
3
4
5
6
7
8
9
10
ちょっと無駄に長くなっちゃいましたが、
こういうことも出来ます。
use v5.10; use strict; use warnings; my $sum = 0; $sum += $_ for <>; say $sum;
今度はこんな感じ。
$ perl bbb.pl < data.txt
55
さて、本題。
例えば、200,000行くらいあったとします。
つまり、こんな感じでテストデータを作ります。
$ perl -E 'say $_ for 1..200_000' > more_data.txt
次に、それらを配列に入れるまでの時間を計測します。
use v5.10; use strict; use warnings; use Time::HiRes qw/time/; my $start = time(); my @data = <>; say 'count = ' . scalar(@data); say time() - $start;
結果はこんな感じ。
$ perl ccc.pl < more_data.txt
count = 200000
0.171335935592651
あと、各要素の最後に改行が残っているので、
場合によってはchomp
する必要もある。(*1)
次にsplit
を使う例。
use v5.10; use strict; use warnings; use Time::HiRes qw/time/; my $start = time(); my @data = split "\n", do { local $/; <> }; say 'count = ' . scalar(@data); say time() - $start;
$ perl ddd.pl < more_data.txt
count = 200000
0.0536541938781738
この方法は、以下のページを参考にさせて頂きました。
perlで頑張って新人女子を助けた。 #paizahack_01 – blog.aklaswad.com
最後は、sysread
を使う例。
use v5.10; use strict; use warnings; use Time::HiRes qw/time/; my $read_size = 200_000 * 7; # どんぶり勘定 my $start = time(); my $buf; if ( $read_size <= sysread(STDIN, $buf, $read_size) ) { exit( 1 ); # 全部読み込めてない } my @data = split "\n", $buf; say 'count = ' . scalar(@data); say time() - $start;
コードはアレですが、2つ目と同じくらい早いですね。
$ perl eee.pl < more_data.txt
count = 200000
0.0531890392303467
で、「こんなの、なんに使うの?」って話だけど、
例えば、標準入力で取得した改行区切りの文字列を受け取るのに、
少しでも早く配列に格納したい場合にオススメです。
おしまい。
Leave a Comment