ファイルの各行を「読み込む」のが「xargs」よりはるかに速い理由

ファイルの各行を「読み込む」のが「xargs」よりはるかに速い理由

私は30M行を含む大きな入力ファイルを持っています\r\n。私は愚かなことをし、read -rすべての行を計算する速度を比較することにしました(2文字以上を分割することは不可能に見えるので、xargs最初の行を削除します)。私の2つのコマンドは次のとおりです。\rxargs

time tr -d '\r' < input.txt | xargs -P 1 -d '\n' -I {} echo "{}" | wc -l
time while read -r p || [ -n "$p" ]; do echo "$p"; done < input.txt | wc -l

ここで2番目の解決策はたくさん急いで。なぜそんなことですか?

私はこれがファイルの行数を数える正しい方法ではないことを知っています。この質問はただ私の観察的関心からのものです。

答え1

はい、予想通り、これは実際にxargs -P 1 -d '\n' -I {} echo "{}"プロセスを分岐し、各入力行に対して親プロセスで終了するのを待っている間、子プロセスから独立したプロセスを実行する基本コマンドと同じです。xargs -rd '\n' -n1echoecho

したがって、これは同じシェルプロセスで非効率的な組み込み機能とすべての組み込み機能を使用するよりもreadはるかに多くの作業です。echo

xargsxargs(少なくとも一部の設定と最新バージョンでは)プロセスを分岐せずに内部でbusyboxを呼び出すGNUの代わりにbusyboxを使用すると、ループよりはるかに高速ですechobash

より関連性の高い比較のために、以下を比較する必要があります。

tr -d '\r' | xargs -rd'\n' -n1

そして

tr -d '\r' |
  while IFS= read -r line || [ -n "$line" ]; do
   /bin/echo "$line"
  done

ほとんどの時間がプロセスを分岐して独立して実行するのに費やされるため、同様の結果が得られますecho

ここでは、出力seq 3e7と測定pv -al > /dev/nulla1秒あたりの平均線で測定されたスループット)に関する解決策を得ました。l

  • busybox xargsは1.12M/sです。
  • 70k/sのエコーを内蔵したbashループ
  • GNU xargsは860/sです。
  • /bin/echo を使用した bash ループの場合、850/s

関連情報