なぜトイレはとても遅いのですか?


17

なぜwcユーティリティはこんなに遅いのですか?

大きなファイルで実行すると、md5sumの約20倍の時間がかかります。

MyDesktop:/tmp$ dd if=/dev/zero bs=1024k count=1024 of=/tmp/bigfile
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.687094 s, 1.6 GB/s

MyDesktop:/tmp$ time wc /tmp/bigfile 
         0          0 1073741824 /tmp/bigfile

real    0m45.969s
user    0m45.424s
sys     0m0.424s

MyDesktop:/tmp$ time md5sum /tmp/bigfile 
cd573cfaace07e7949bc0c46028904ff  /tmp/bigfile

real    0m2.520s
user    0m2.196s
sys     0m0.316s

ファイルがヌルでいっぱいになっていることによる単なる奇妙なエッジ状態ではなく、ファイルがランダムデータで満たされていたり、テキストファイルであっても、パフォーマンスに同じ違いが見られます。

(これはUbuntu 13.04、64ビット上にあります)


行数だけを気にする人への注意:wc -l <​​filename>は、非常に大きなファイルでははるかに高速です。
EL

回答:


27

そこでソースに行きましたが、2バイト文字の処理が遅いようです。基本的に、読み込まれたすべての文字に対してmbrtowc()、それをワイド文字に変換するために呼び出す必要があり、その後、そのワイド文字が単語区切り文字、行区切り文字などであるかどうかをテストします。

実際、ロケールLANG変数をデフォルトen_US.UTF-8(UTF-8はマルチバイト文字セット)から変更して " C"(単純なシングルバイト文字セット)に設定wcすると、シングルバイト最適化を使用でき、大幅に高速化されます。以前の約4分の1しかかかりません。

さらに、単語(-w)、行の長さ(-L)、または文字(-m)のカウントを行う場合にのみ、各文字をチェックする必要があります。バイトおよび/または行カウントのみを行う場合、ワイド文字の処理をスキップして、非常に迅速に実行できます-よりも高速ですmd5sum

私はを通してそれを実行gprofし、マルチバイト文字を処理するために使用される関数(mymbsinit()mymbrtowc()myiswprint()それが持っているので、など)は30のみで実行時間の%、およびバッファを介してのステップがはるかに複雑であることコードについて取り上げています可変サイズの文字のバッファーを介して可変サイズのステップを処理し、バッファーをまたがる部分的に完成した文字をバッファーの先頭に戻し、次回に処理できるようにします。

探すべきものがわかったので、いくつかのユーティリティのutf-8の遅さについて言及しているいくつかの投稿を見つけました。

/programming/13913014/grepping-a-huge-file-80gb-any-way-to-speed-it-up http://dtrace.org/blogs/brendan/2011/12/08 / 2000x-performance-win /


2
ああ、あなたはOPだと気付いた。:p
イヴァンチャウ

2
これは最も支持された答えですが、無関係です。md5sum単語番号を数えることはできwcず、ファイルのmd5ハッシュを計算しません!それは、テキストを書くときに私のタイプライターに比べて私の車がなぜそんなに遅いのかを尋ねるようなものです。
user49468

5
@ user49468:両方とも入力ファイルの各バイトを読み取る必要があるため、両方ともIOバインドであると想定するのが妥当です。この答えwcは、マルチバイト文字を処理する場合、実際にはCPUに依存していることを証明しています。
–MSalters

2
@ user49468:wcとmd5sumは異なる処理を行う場合がありますが、両方ともファイルを読み取り、比較的単純な計算を行います。チェックサムを計算し、バイトをカウントし、単語の区切りと改行を計算します。まあ、私それが簡単だと思ったが、マルチバイト文字セットの余分な複雑さを考慮していなかった。「どうして私の車はミニバンよりも店に行くのが20倍速いの?」と尋ねるようなものです。この2つの間に多少の違いが予想されますが、20倍の違いはありません。
ジョニー

1
@Johnny you car / minivanの比較には、どちらもあなたを店に運ぶように設計されているという側面がありません。そのため、速度の比較が行われています。あなたの車をストライプ塗装車両と比較するのがより適切です。両方が道路を使用しているという理由だけで、ストライプの画家は買い物に行くのに適していないため、速度は関係ありません。
user49468

1

ただの推測ができますどのように関連してオレンジにリンゴを比較している種類のwcものを対やっているmd5sumやっています。

md5sumのタスク

md5sumファイルを処理するときは、ファイルをストリームとして単純に開き、メモリをほとんど必要としないMD5チェックサム関数を介してストリームの実行を開始します。基本的にはCPUとディスクI / Oがバインドされています。

wcのタスク

ときwc、それはただ一度に文字ファイルを解析するより、その後多くのことをやっている実行します。ファイルの構造、文字の境界がどこにあるのか、単語の境界であるかどうかを一度に判断する行を実際に分析する必要があります。

次の文字列と、各アルゴリズムがそれらを解析する際にどのように移動する必要があるかを考えてください。

“Hello! Greg”
“Hello!Greg”
“Hello\nGreg”
“A.D.D.”
“Wow, how great!”
“wow     \n\n\n    great”
“it was a man-eating shark.”

MD5では、これらの文字列を1文字ずつ簡単に移動します。wcそれは言葉&ライン境界だかを決定し、それが見ている出現回数を追跡する必要があります。

追加のWCディスカッション

2006年のこのコーディングの課題はwc、.NETでの実装について説明しています。いくつかの疑似コードを見ると、この問題は非常に明白でwcあるため、他の操作よりもはるかに遅いように見える理由を明らかにするのに役立つかもしれません。


1
あなたは、標準のUnix wcコマンド(少なくとも、Ubuntuに付属しているものではありません)とは異なるものを説明しています。そのトイレはカウントされませんユニークな言葉、言葉だけなので、「ハローハローワールド」を3つの言葉ではなく、2です
ジョニー

この理論に基づくと、行を数えるなどのより単純なタスクがより迅速に進むように思えます。「wc」を変更して行数を指定すると、結果が大幅に変更されますか?'wc -l'
ジョシュアミラー

@ジョニー-あなたが言ったユニークな言葉を数えるとは決して言わなかった。wcファイルを解析するときに複数のものをカウントします。ファイルを解析するときに、単語、行、およびバイトの数をカウントします。manページを読んでください!
slm

@JoshuaMiller- wc行のみをカウントするように指示すると、内部の解析が制限されて、これらのことだけをカウントするのか、それともすべてをカウントしたとしても行の結果のみをレポートするのかが不明です。
slm

@slmあなたはそれがユニークな単語を数えると言った、あなたの例は 「こんにちは!Greg」は、Hello 1、Greg 1、つまり各単語のカウントになります。そして、リンクした.Netプロジェクトは、「その主なタスクの1つは、一連のデータを調べて特定の単語の繰り返し回数をカウントすることです。たとえば、「He​​llo、yes hello」という文が与えられた場合、 Helloという単語が2回使用され、yesという単語が1回使用されました。」現実にはエコーの結果「こんにちは、はいこんにちは」| wc --wordsは「3」であり、「Hello:2、Yes:1」ではありません
ジョニー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.