大きなテキストファイル(1.5 G)があります。
Linuxで最も高速で信頼性の高いツールを教えてください。
私は通常使用します:
awk '!x[$0]++' file.txt
しかし、htop
コマンドを使用すると、メモリ使用量が増加していることがわかります。
巨大なファイルで最も速くて信頼性の高いものを知りたい。
uniq?
sort?
sed?
awk?
どうして?
大きなテキストファイル(1.5 G)があります。
Linuxで最も高速で信頼性の高いツールを教えてください。
私は通常使用します:
awk '!x[$0]++' file.txt
しかし、htop
コマンドを使用すると、メモリ使用量が増加していることがわかります。
巨大なファイルで最も速くて信頼性の高いものを知りたい。
uniq?
sort?
sed?
awk?
どうして?
回答:
各ソリューションがどのように機能するかを考えてみましょう。
uniq
これには、ファイルがすでにソートされている必要があります。そうでない場合は、sort
最初にパイプで通す必要があります。つまりsort
、ファイル全体をメモリに読み取り、並べ替え(O(n log n)
)してから、パイプに書き込みます。の作業はuniq
、入力の隣接する行を比較するだけなので、非常に安価です。
sort -u
これはの作業を組み合わせたものですsort | uniq
。これは、awk
スクリプトのようにすべての固有の入力をメモリに収集する必要がありますが、出力を生成する前にそれらを並べ替えるのに時間を浪費します。これはO(n log n)
ですが、この場合n
は一意のアイテムの数であり、すべての入力ではありません。したがって、パイプよりも優れています。
sed
なぜあなたがこれをリストしたのかはわかりませんsed
。これを行うための良い方法はまったく考えられないからです。最初に並べ替えてsed
スクリプトにパイプする場合、隣接する行を比較する方法があるかもしれません。だから、sed
何をするかuniq
、そしてuniq
おそらくそれを可能な限り効率的に行うでしょう。
awk
必要な作業が最小限で済むため、これはおそらく最良の方法です。各行を読み取るときに、効率的なハッシュルックアップを実行して、行が既にメモリにあるかどうかを確認し、一意の行のみをハッシュキーとして、カウンターを値として格納します。(その行が以前に存在していなかった場合、条件はtrueになるため、その行は印刷されます。それ以外の場合は印刷されません。)これはO(n)
時間とO(uniq n)
メモリを使用します。
すべてのメソッドは、入力をソートするため、または重複を削除できるように、どの入力が表示されたかを追跡するためにかなりの量のメモリを使用します。
awk
説明では、メモリの使用量が増える理由も説明されています。並べ替えを行うものはすべてこれも行うことになり、1)おそらく一度にすべてを使用します。2)一意のキーと重複するキーの数に応じて、わずかに多く使用します。
sort
一時的なファイルを使用して(インテリジェントな方法で)、メモリがいっぱいにならないようにします。そのメモリ使用量は制限されています。境界は、いくつかのソート実装でカスタマイズ可能です。システムにメモリをランダムにディスクにスワップさせる(システム上のアプリケーションにも影響する)よりも効率的です。
awk
、メモリが不足するケースに遭遇した場合はsort
、これに対処するように設計されているため、唯一の解決策になる可能性があります。一方、ディスクの読み取りと書き込みはすべて速度が低下するため、完了するまでに時間がかかる可能性があります。このような大量のデータを扱う場合は、テキストファイルではなくDBMSを使用しているはずです。
O(n log n)
か?それとも他の場所から知っているだけですか?
ここに示すように、sortが最速のuniqツールであるように見えます-> 大きなワードリストで重複を削除する最も速い方法は?
uniq
ソートされたリストであっても、gnu がひどく遅いように見えることを指摘したかっただけです。
ソートされたファイル名のリストからディレクトリプレフィックスのリストを取得しようとしました:
$ pv all_files | cut -d '/' -f 1,2,3,4 | uniq > all_prefixes
36.7GiB 0:07:41 [81.4MiB/s]
$ pv all_files | cut -d '/' -f 1,2,3,4 | sort -u > all_prefixes2
36.7GiB 0:03:14 [ 193MiB/s]
$ pv all_files | cut -d '/' -f 1,2,3,4 | awk '!x[$0]++' > all_prefixes3
36.7GiB 0:02:18 [ 270MiB/s]
sort -uはuniqの2倍の速度で表示されます。これは、stdinからのsortの読み取りとstdoutへの書き込みで行われるため、並列化はまだ行われていません。リストをソートする必要がないので、なぜuniqがソートよりもはるかに遅くなるのか私にはわかりません...
このコマンドのoutpufは非常に小さく(多くの重複があります)、264kbのみで、pvが実行された直後にソートが終了します。
コマンドの順序を変えても同じ速度が維持されます。ここでのフローは、ディスクアクセスやキャッシュではなく、ここでのCPU時間によって制限されます(RAMは8 GBしかなく、スワップは使用されていません)。
私はこれをgnu coreutils sortとuniqおよびgnu awkを備えたfedora 31マシンで実行しています。ロケールはen_US.UTF-8に設定されています
UPDATE、これは私にかなり興味をそそられたので、私はさらにいくつかのテストを行いました、切り取られた部分を邪魔にならないように配置して、ファイルが適切にソートされていることを確認しましょう
cat all_files | cut -d '/' -f 1,2,3,4 | sort -T . > test
これには8.4分かかります。テストは7.9GBになりました
パイプではなくファイルでこれらのツールを実行してみましょう。これにより、これらのツールは、並べ替えがマルチスレッドのようにさらに最適化できます。また、より高速なssdから。
/ tmpにある一時ファイルで巧妙なトリックを実行しているため、sortも大量のメモリを使用していることに気付かないかもしれません。問題、それが上記のコマンドで-T。フラグが必要な理由です)
$ time sort -u test > /dev/null
339.24user 3.54system 1:28.87elapsed 385%CPU (0avgtext+0avgdata 2365856maxresident)k
9555544inputs+0outputs (0major+591298minor)pagefaults 0swaps
$ time awk '!x[$0]++' test > /dev/null
51.15user 1.55system 0:52.94elapsed 99%CPU (0avgtext+0avgdata 10976maxresident)k
0inputs+0outputs (0major+1923minor)pagefaults 0swaps
$ time uniq test > /dev/null
421.89user 2.76system 7:06.63elapsed 99%CPU (0avgtext+0avgdata 1980maxresident)k
52712inputs+0outputs (0major+79minor)pagefaults 0swaps
したがって、あなたのawkソリューションはこれらの3の中で最速であり、実際には最小のメモリを使用するようです
update2 と、よりシンプルなロケールになりました
$ export LC_ALL=c
$ time sort -u test > /dev/null 1.2m ? Tue Apr 21 17:09:22 2020
119.18user 3.64system 0:38.24elapsed 321%CPU (0avgtext+0avgdata 2013472maxresident)k
$ time awk '!x[$0]++' test > /dev/null 1161ms ? Tue Apr 21 17:07:31 2020
67.23user 2.50system 1:10.16elapsed 99%CPU (0avgtext+0avgdata 10480maxresident)k
7187520inputs+0outputs (0major+1912minor)pagefaults 0swaps
$ time uniq test > /dev/null
22.05user 2.02system 0:24.24elapsed 99%CPU (0avgtext+0avgdata 1488maxresident)k
2959648inputs+0outputs (1major+72minor)pagefaults 0swaps
今回はuniqがレースに勝利します...StéphaneChazelasがコメントで示唆しているように、ロケールをCに設定すると、並べ替えとuniqがかなり速くなります!
sort
とuniq
?どのロケール?
time
か?