次のコマンドは結果を出力するのに約10分かかります。
find . -name "muc*_*_20160920_*.unl*" | xargs zcat |
awk -F "|" '{if($14=="20160920100643" && $22=="567094398953") print $0}'| head
パフォーマンスをどのように向上させることができますか?
ベストアンサー1
これはすでにかなり最適化されています。詳細を知らないと、ボトルネックが何であるかを知ることは困難です。
- ストレージタイプ(HD、SSD、ネットワーク、RAID)
- 一致するファイルの数と平均サイズ
- ディレクトリやその他の不一致ファイルの数
- 1行あたりのフィールド数
- 平均行長
どんな状況でもできること:
- /がサポートしている場合はor
-print | xargs
に変更してください-exec cmd {} +
。これは間違っているだけでなく、どの文字が空白なのかを調べるために文字をデコードし、高価な引用を行う必要があるため、コストがかかります。-print0 | xargs -r0
find
xargs
-print | xargs
xargs
- ロケールをC(
export LC_ALL=C
)に変更しました。ここに含まれるすべての文字(|
ファイルの内容の10進数、ファイル名のラテン文字、ピリオド、アンダースコアを含む)は移植可能な文字セットの一部であるため、文字セットがUTF-8または他のマルチバイト文字の場合は、C言語のシングルバイト文字セットこの言語に切り替えると、find
多くの作業が節約されますawk
。 - 部品を
awk
次のように単純化しますawk -F "|" '$14 == "20160920100643" && $22 == "567094398953"'
。 - 出力をにパイプしているので、出力バッファリングを無効にして、できるだけ早くこれらの10行を出力できます
head
。またはawk
経由で使用できます。またはinを追加することもできます。gawk
mawk
fflush()
if (++n == 10) exit
awk
要約する:
(export LC_ALL=C
find . -name "muc*_*_20160920_*.unl*" -exec zcat {} + |
awk -F "|" '$14 == "20160920100643" && $22 == "567094398953" {
print; if (++n == 10) exit}')
CPUがボトルネックを引き起こしている場合は、マルチコアGNUシステムで次のことを試すことができます。
(export LC_ALL=C
find . -name "muc*_*_20160920_*.unl*" -print0 |
xargs -r0P 4 -n 100 sh -c '
zcat "$@" |
awk -F "|" "\$14 == "20160920100643" && \$22 == "567094398953" {
print; fflush()}"' sh | head)
zcat | awk
100ファイルのバッチで4つのジョブを並列に実行します。
タイムスタンプの場合は、以前20160920100643
に最後に変更されたファイルを除外できます。 GNUまたはBSDのfind
場合-newermt '2016-09-20 10:06:42'
。
行にフィールド数が多い場合は、行を分割して余りにもawk
多くのフィールドを割り当てると$n
不利益になります。最初の22フィールドのみを考慮するアプローチを使用すると、スピードを上げることができます。
grep -E '^([^|]*\|){13}20160920100643(\|[^|]*){7}\|567094398953(\||$)'
awk
コマンドより 。 GNUを使用して並列方式では最初にライン出力にオプションをgrep
追加するか、非並列方式では10回一致後に停止します。--line-buffered
-m 10
要約すると、CPUにボトルネックがあり、システムに4つ以上のCPUコア、400以上のmuc *ファイルがあり、GNUシステム(通常はgrep
GNUよりはるかに高速ですawk
)を使用しています。
(export LC_ALL=C
find . -name "muc*_*_20160920_*.unl*" -newermt '2016-09-20 10:06:42' -print0 |
xargs -r0P 4 -n 100 sh -c '
zcat "$@" |
grep --line-buffered -E \
"^([^|]*\|){13}20160920100643(\|[^|]*){7}\|567094398953(\||$)"
' sh | head)
並列アプローチでは、互いに混合されたコマンド出力を得ることができますgrep
(ラインバッファリングを使用し、数キロバイト未満のラインを提供してもライン境界は維持する必要があります)。