unpigzを使用してください。

unpigzを使用してください。

私は7.6GBのgzipファイルのレコードをカウントしようとしています。zcatこのコマンドの使用方法はほとんどありません。

$ zcat T.csv.gz | wc -l
423668947

この方法は機能しますが、時間がかかりすぎます(計算に10分以上)。私は次のようなより多くの方法を試しました。

$ sed -n '$=' T.csv.gz
28173811
$ perl -lne 'END { print $. }' < T.csv.gz
28173811
$ awk 'END {print NR}' T.csv.gz
28173811

3つのコマンドはすべて非常に高速に実行されますが、誤った数の28173811が表示されます。

最小時間でレコード計算を実行するには?

答え1

言及したsedperlとコマンドはawk正確かもしれませんが、すべて読んでください。圧縮データを入力し、その中に改行文字を数えます。これらの改行は、圧縮されていないデータの改行とは無関係です。

圧縮されていないデータの行数を計算するには、解凍できません。あなたのアプローチがzcat正しいアプローチであり、データが大きすぎるため〜する開梱には時間がかかります。

圧縮と解凍を処理するほとんどのユーティリティは、gzipこれを行うために同じ共有ライブラリルーチンを使用する可能性が高いです。作業を高速化する唯一の方法は、zlib基本ルーチンよりも高速なルーチン実装を見つけて、zcatそれを使用するために再構築することです。

答え2

unpigzを使用してください。

Kosalonandaの答えは正しいです。〜するコンテンツをスキャンする前に、ファイル全体を解凍する必要があります。/bin/gunzip単一コアでできるだけ早くこれを行います。豚豚gzip複数のコアを使用できる並列実装です。

pigz残念ながら、通常のgzipファイル自体の解凍は並列化できませんが、読み取り、書き込み、チェックサムなどの関連タスクを別のスレッドで実行する改善されたバージョンのgzipを提供します。一部の高速ベンチマークでは、コアi5システムよりもほぼ倍速です。gunzipunpigzunpigzgunzip

pigzお気に入りのパッケージマネージャを使用してインストールし、代わりにunpigz使用してくださいgunzip。したがって、あなたのコマンドは次のようになります。unpigz -czcat

$ unpigz -c T.csv.gz | wc -l

もちろん、これらすべては、ボトルネックがディスクではなくCPUであると想定しています。

答え3

すべての配管の問題は、基本的に作業量が2倍になるということです。解凍速度に関係なく、データはまだ別のプロセスに移動する必要があります。

PerlはPerlIO::gzipgzipで圧縮されたストリームを直接読み取ることができます。したがって、減圧速度が一致しない場合でも、次の利点がありますunpigz

#!/usr/bin/env perl

use strict;
use warnings;

use autouse Carp => 'croak';
use PerlIO::gzip;

@ARGV or croak "Need filename\n";

open my $in, '<:gzip', $ARGV[0]
    or croak "Failed to open '$ARGV[0]': $!";

1 while <$in>;

print "$.\n";

close $in or croak "Failed to close '$ARGV[0]': $!";

13MB gzip圧縮ファイル(1.4GBに解凍)を持つ古いコンピュータで試しました。16GB RAMを搭載した2010年のMacBook Proそして古いものThinkPad T400には8GBのRAMが搭載されています。ファイルはすでにキャッシュにあります。 Macでは、Perlスクリプトはパイプを使用するよりはるかに高速ですが(5秒対22秒)、ArchLinuxではunpigzに敗北します。

$時間-p ./gzlc.pl spy.gz
1154737
実際の4.49
ユーザー 4.47
システム0.01

比較的

$時間-p unpigz -c spy.gzトイレ-l |
1154737
実際の3.68
ユーザー 4.10
システム 1.46

そして

$時間-p zcat spy.gzトイレ-l |
1154737
レアル6.41
ユーザー 6.08
システム0.86

明らかに、unpigz -c file.gz | wc -lスピードの面では使用量が勝者です。そしてどんなに短くても、単純なコマンドラインは確かにプログラム作成よりも優れています。

答え4

これは zgrepフラグ-c$パラメータを使用して行うことができます。

この場合、-c はコマンド出力に行数を一致させるように指示し、正規表現 $ は行末と一致するため、すべての行またはファイルと一致します。

zgrep -c $ T.csv.gz 

@StéphaneChazelasが述べたように - 元の提案と同様のパフォーマンスを提供する必要があるスクリプトzgrepだけです。zcatgrepzcat | wc -l

関連情報