echoと<<<、またはBash Awardでエコーを無駄に使用しますか?

echoと<<<、またはBash Awardでエコーを無駄に使用しますか?

これまでcat報酬は役に立たないよく知られていて言及されている役に立たない使用echo(この質問には関係ありません)。 「Bashで役に立たない使用上」があるべきかどうか疑問に思いますecho。いくつかの非常に非科学的な測定によると、パイプはheredocsとherestringsよりはるかに遅いようです。

  • 継承文書:

    for reps in 1 2 3
    do
        time for i in {1..1000}
        do
            cat <<'END'
    test string
    END
        done > /dev/null
    done
    
    real    0m1.786s
    user    0m0.212s
    sys     0m0.332s
    
    real    0m1.817s
    user    0m0.232s
    sys     0m0.332s
    
    real    0m1.846s
    user    0m0.256s
    sys     0m0.320s
    
  • ハースト

    for reps in 1 2 3
    do
        time for i in {1..1000}
        do
            cat <<< 'test string'
        done > /dev/null
    done
    
    real    0m1.932s
    user    0m0.280s
    sys     0m0.288s
    
    real    0m1.956s
    user    0m0.248s
    sys     0m0.348s
    
    real    0m1.968s
    user    0m0.268s
    sys     0m0.324s
    
  • リダイレクト

    for reps in 1 2 3
    do
        time for i in {1..1000}
        do
            echo 'test string' | cat
        done > /dev/null
    done
    
    real    0m3.562s
    user    0m0.416s
    sys     0m0.548s
    
    real    0m3.924s
    user    0m0.384s
    sys     0m0.604s
    
    real    0m3.343s
    user    0m0.400s
    sys     0m0.552s
    

一般に、heredocsとHerestringsの速度はほぼ同じです(これはいくつかのテストのうちの1つのデータセットにすぎません)。一方、リダイレクトは常に50%以上遅いです。私が何か間違って理解したのですか?それとも、これはBashから標準入力を読み取るコマンドの一般的な規則として使用できますか?

ベストアンサー1

まず、パフォーマンスに焦点を当てます。私はDebianスクレープを実行しているx86_64プロセッサでわずかに異なるプログラムのベンチマークを実行しましたが、そうでなければほとんどアイドル状態でした。

herestring.bash、herestringを使用して入力行を渡します。

#! /bin/bash
i=0
while [ $i -lt $1 ]; do
  tr a-z A-Z <<<'hello world'
  i=$((i+1))
done >/dev/null

heredoc.bash、heredocを使用して入力行を渡します。

#! /bin/bash
i=0
while [ $i -lt $1 ]; do
  tr a-z A-Z <<'EOF'
hello world
EOF
  i=$((i+1))
done >/dev/null

echo.bashecho入力ラインを渡すには、パイプを使用します。

#! /bin/bash
i=0
while [ $i -lt $1 ]; do
  echo 'hello world' | tr a-z A-Z
  i=$((i+1))
done >/dev/null

比較のために、ATT ksh93とダッシュの下でスクリプトの時間も測定しました(herestring.bashダッシュにはこの文字列がないため除く)。

中央値トリプルは次のとおりです。

$ time bash ./herestring.bash 10000
./herestring.bash 10000  0.32s user 0.79s system 15% cpu 7.088 total
$ time ksh ./herestring.bash 10000
ksh ./herestring.bash 10000  0.54s user 0.41s system 17% cpu 5.277 total
$ time bash ./heredoc.bash 10000
./heredoc.bash 10000  0.35s user 0.75s system 17% cpu 6.406 total
$ time ksh ./heredoc.bash 10000  
ksh ./heredoc.sh 10000  0.54s user 0.44s system 19% cpu 4.925 total
$ time sh ./heredoc.bash 10000  
./heredoc.sh 10000  0.08s user 0.58s system 12% cpu 5.313 total
$ time bash ./echo.bash 10000
./echo.bash 10000  0.36s user 1.40s system 20% cpu 8.641 total
$ time ksh ./echo.bash 10000
ksh ./echo.sh 10000  0.47s user 1.51s system 28% cpu 6.918 total
$ time sh ./echo.sh 10000
./echo.sh 10000  0.07s user 1.00s system 16% cpu 6.463 total

結論として:

  • HeredocはHerestringよりも高速です。
  • echoパイプラインは著しく高速になりましたが、それほど速くはありません。 (これはおもちゃプログラムであることを覚えておいてください。実際のプログラムでは、ほとんどの処理時間がtrここにある呼び出しに含まれています。)
  • 速度が必要な場合は、bashを捨てて代わりにdashまたはより良いkshを呼び出してください。 Bashのパフォーマンスは相対的な遅い速度を補完しませんが、kshはパフォーマンスと速度の両方を備えています。

パフォーマンスに加えて、明確さと移植性があります。<<<ksh93/bash/zsh 拡張ですが、よくecho … |知られていません<<。 ksh88/pdksh または POSIX sh では機能しません。

より明確であると言える唯一の場所は<<<区切り記号の内側です。

foo=$(tr a-z A-Z <<<'hello world')

比較済み

foo=$(tr a-z A-Z <<'EOF'
hello world
EOF
)

(ほとんどのシェルはそれを含む行の末尾にある角括弧を処理できません<<EOF。)

おすすめ記事