この場合、「sed」が「awk」よりもはるかに高速でないのはなぜですか

魏淳周

私はに関連するいくつかのパフォーマンスの問題を理解しようとしていますsedawk、私は次のような実験を行いました

$ seq 100000 > test
$ yes 'NR==100001{print}' | head -n 5000 > test.awk
$ yes '100001{p;b}' | head -n 5000 > test.sed
$ time sed -nf test.sed test
real    0m3.436s
user    0m3.428s
sys     0m0.004s
$ time awk -F@ -f test.awk test
real    0m11.615s
user    0m11.582s
sys     0m0.007s
$ sed --version
sed (GNU sed) 4.5
$ awk --version
GNU Awk 4.2.1, API: 2.0 (GNU MPFR 3.1.6-p2, GNU MP 6.1.2)

ここでは、テストファイルには100000行しか含まれていないためtest.sedおよびのすべてのコマンドtest.awkは操作なしです。どちらのプログラムも、行番号をアドレス(in sed)またはNR(in awkと照合するだけで、コマンドを実行する必要がないと判断できますが、それでも時間コストには大きな違いがあります。なぜそうなのですか?このテストで異なる結果をもたらす、異なるバージョンsedawkインストール済みの人はいますか?

編集mawkoriginal-awk@ mosvyによって提案された)(@ GregA.Woodsによって提案されたdebianベースのシステムでの「onetrueawk 」の名前の結果をperl以下に示します。

$ time mawk -F@ -f test.awk test
real    0m5.934s
user    0m5.919s
sys     0m0.004s
$ time original-awk -F@ -f test.awk test
real    0m8.132s
user    0m8.128s
sys     0m0.004s
$ yes 'print if $.==100001;' | head -n 5000 > test.pl
$ time perl -n test.pl test
real    0m33.245s
user    0m33.110s
sys     0m0.019s
$ mawk -W version
mawk 1.3.4 20171017
$ perl --version
This is perl 5, version 28, subversion 1 (v5.28.1) built for x86_64-linux-thread-multi

とを置き換え-F@-F ''も、gawkの場合は目に見える変化はありませんmawkoriginal-awk空をサポートしていませんFS

編集2 @ mosvyによるテストでは、21秒sedと11秒の異なる結果が得mawkられます。詳細については、以下のコメントを参照してください。

ジグリナガ

awkより幅広い機能セットがありsed、構文がより柔軟です。したがって、スクリプトの解析と実行の両方に時間がかかることは不合理ではありません。

サンプルコマンド(中括弧内の部分)は実行されないため、時間に敏感な部分をテスト式にする必要があります。

awk

まず、awkのテストを見てください

NR==100001

gprof(GNU awk 4.0.1)でその効果を確認してください

  %累積自己自己合計
 時間秒秒呼び出しs /呼び出しs /呼び出し名
 55.8919.73 19.73 1 19.7335.04解釈
  8.9022.87 3.14 500000000 0.00 0.00 cmp_scalar 
  8.64 25.92 3.05 1000305023 0.00 0.00 free_wstr 
  8.61 28.96 3.04 500105014 0.00 0.00 mk_number 
  6.09 31.11 2.15 500000001 0.00 0.00 cmp_nodes 
  4.18 32.59 1.48 500200013 0.00 0.00 unref 
  3.68 33.89 1.30 500000000 0.00 0.00 eval_condition 
  2.21 34.67 0.78 500000000 0.00 0.00 update_NR

時間の約50%は、解析されたスクリプトから生成されたオペコードを実行するための最上位ループである「解釈」に費やされます。

テストが実行されるたびに(つまり、5000スクリプト行* 100000入力行)、次のことawkを行う必要があります。

  • 組み込み変数「NR」(update_NR)をフェッチします
  • 文字列 "100001"(mk_number)を変換します
  • それらを比較します(cmp_nodescmp_scalareval_condition)。
  • 比較に必要な一時オブジェクトを破棄します(free_wstrunref

他のawk実装では、まったく同じ呼び出しフローはありませんが、変数を取得し、自動的に変換してから比較する必要があります。

そして

比較すると、sedでは、「テスト」ははるかに制限されています。単一のアドレス、アドレス範囲、または何もない場合(コマンドが行の最初のものである場合)でありsed、最初の文字からそれがアドレスであるかコマンドであるかを判別できます例では、

100001

...単一の数値アドレス。プロファイル(GNU sed 4.2.2)は

  %累積自己自己合計
 時間秒秒呼び出しs / call s / call name 
 52.01 2.98 2.98 100000 0.00 0.00 execute_program 
 44.16 5.51 2.53 1000000000 0.00 0.00 match_address_p 
  3.84 5.73 0.22 match_an_address_p 
[...] 
  0.00 5.73 0.00 5000 0.00 0.00 in_integer

繰り返しますが、時間の約50%がトップレベルにありますexecute_programこの場合、入力行ごとに1回呼び出され、解析されたコマンドをループします。ループはアドレスチェックから始まりますが、例ではそれだけではありません(後述)。

入力スクリプトの行番号は、コンパイル時に解析されました(in_integer)。これは、入力のアドレス番号ごとに1回だけ実行する必要があります。5000回であり、全体の実行時間に大きな影響を与えることはありません。

つまり、アドレスチェックはmatch_address_p、(構造体とポインタを介して)すでに使用可能な整数のみを比較します。

さらなるsed改善

プロファイルは、それmatch_address_pが2 * 5000 * 100000回呼び出されることを示しています。script-line * input-lineごとに2回これは、舞台裏で、GNUsedが「スターティングブロック」コマンドを処理するためです。

100001{...}

ブロックの終わりへの否定されたブランチとして

100001!b end; ... :end

このアドレス一致はすべての入力行で成功し、ブロックの終わりに分岐します(})。そのブロックエンドにはアドレスが関連付けられていないため、別の成功した一致です。それが、に多くの時間が費やされている理由を説明していexecute_programます。

そのsedため、未使用のを省略し;b、結果として不要なを省略して、{...}のみを残すと、式はさらに高速になり100001pます。

  %累積自己自己合計           
 時間秒秒呼び出しs /呼び出しs /呼び出し名    
 71.431.40 1.40 500000000 0.00 0.00 match_address_p 
 24.49 1.88 0.48 100000 0.00 0.00 execute_program 
  4.08 1.96 0.08 match_an_address_p

これにより、match_address_p呼び出しの数が半分になり、費やされる時間のほとんどが削減されますexecute_program(アドレスの一致が成功しないため)。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

この場合、PythonがC ++よりも高速なのはなぜですか?

分類Dev

同じ目的で使用した場合、.html()が.text()よりもはるかに高速なのはなぜですか?

分類Dev

この場合、mclappyが適用よりも遅いのはなぜですか?

分類Dev

配列がArrayListよりもはるかに高速なのはなぜですか?

分類Dev

any()がinよりもはるかに高速なのはなぜですか?

分類Dev

PythonのこのコードがC ++よりもはるかに高速なのはなぜですか?

分類Dev

サブクエリ結合が直接結合よりもはるかに高速なのはなぜですか

分類Dev

array.pushがarray [n] = valueよりも高速な場合があるのはなぜですか?

分類Dev

この単純なループの実行において、PHP7がPython3よりもはるかに高速なのはなぜですか?

分類Dev

ここでJavaがCよりも高速に実行されるのはなぜですか?

分類Dev

配列を乗算する場合、リスト内包表記がnumpyよりもはるかに高速なのはなぜですか?

分類Dev

この操作がGPUよりもCPUで高速に実行されるのはなぜですか?

分類Dev

このコードでCPUがGPUよりも高速に実行されるのはなぜですか?

分類Dev

C#での計算がPythonよりもはるかに高速なのはなぜですか

分類Dev

ターミナルでMacVimがVimよりもはるかに高速なのはなぜですか?

分類Dev

ifstream :: readがイテレータを使用するよりもはるかに高速なのはなぜですか?

分類Dev

Eigensのmean()メソッドがsum()よりもはるかに高速なのはなぜですか?

分類Dev

GHCの場合-この小さなプログラムのレイジーバージョンがループベースのバリアントよりもはるかに高速なのはなぜですか?

分類Dev

文字列:indexOfがcontainsよりも大幅に高速なのはなぜですか?

分類Dev

Matlabで。*演算子がスカラーの*よりも速い場合があるのはなぜですか?

分類Dev

SSHがHTTPよりもはるかに高速であると感じるのはなぜですか?

分類Dev

トーチ:なぜこの照合機能は他の機能よりもはるかに高速なのですか?

分類Dev

str.strip()がstr.strip( '')よりもはるかに高速なのはなぜですか?

分類Dev

numpy.ndarray.Tがnumpy.transpose(numpy.ndarray)よりもはるかに高速なのはなぜですか?

分類Dev

rand()がarc4random()よりもはるかに高速なのはなぜですか?

分類Dev

pandas.grouby.meanが並列実装よりもはるかに高速なのはなぜですか

分類Dev

memcmpがforループチェックよりもはるかに高速なのはなぜですか?

分類Dev

fio seq_writesがddよりもはるかに高速なのはなぜですか?

分類Dev

SSRがSPAよりも高速であるのはなぜですか?

Related 関連記事

  1. 1

    この場合、PythonがC ++よりも高速なのはなぜですか?

  2. 2

    同じ目的で使用した場合、.html()が.text()よりもはるかに高速なのはなぜですか?

  3. 3

    この場合、mclappyが適用よりも遅いのはなぜですか?

  4. 4

    配列がArrayListよりもはるかに高速なのはなぜですか?

  5. 5

    any()がinよりもはるかに高速なのはなぜですか?

  6. 6

    PythonのこのコードがC ++よりもはるかに高速なのはなぜですか?

  7. 7

    サブクエリ結合が直接結合よりもはるかに高速なのはなぜですか

  8. 8

    array.pushがarray [n] = valueよりも高速な場合があるのはなぜですか?

  9. 9

    この単純なループの実行において、PHP7がPython3よりもはるかに高速なのはなぜですか?

  10. 10

    ここでJavaがCよりも高速に実行されるのはなぜですか?

  11. 11

    配列を乗算する場合、リスト内包表記がnumpyよりもはるかに高速なのはなぜですか?

  12. 12

    この操作がGPUよりもCPUで高速に実行されるのはなぜですか?

  13. 13

    このコードでCPUがGPUよりも高速に実行されるのはなぜですか?

  14. 14

    C#での計算がPythonよりもはるかに高速なのはなぜですか

  15. 15

    ターミナルでMacVimがVimよりもはるかに高速なのはなぜですか?

  16. 16

    ifstream :: readがイテレータを使用するよりもはるかに高速なのはなぜですか?

  17. 17

    Eigensのmean()メソッドがsum()よりもはるかに高速なのはなぜですか?

  18. 18

    GHCの場合-この小さなプログラムのレイジーバージョンがループベースのバリアントよりもはるかに高速なのはなぜですか?

  19. 19

    文字列:indexOfがcontainsよりも大幅に高速なのはなぜですか?

  20. 20

    Matlabで。*演算子がスカラーの*よりも速い場合があるのはなぜですか?

  21. 21

    SSHがHTTPよりもはるかに高速であると感じるのはなぜですか?

  22. 22

    トーチ:なぜこの照合機能は他の機能よりもはるかに高速なのですか?

  23. 23

    str.strip()がstr.strip( '')よりもはるかに高速なのはなぜですか?

  24. 24

    numpy.ndarray.Tがnumpy.transpose(numpy.ndarray)よりもはるかに高速なのはなぜですか?

  25. 25

    rand()がarc4random()よりもはるかに高速なのはなぜですか?

  26. 26

    pandas.grouby.meanが並列実装よりもはるかに高速なのはなぜですか

  27. 27

    memcmpがforループチェックよりもはるかに高速なのはなぜですか?

  28. 28

    fio seq_writesがddよりもはるかに高速なのはなぜですか?

  29. 29

    SSRがSPAよりも高速であるのはなぜですか?

ホットタグ

アーカイブ