ファイルから約 300 万行を読み取り、STL マップに挿入しています。そのため、ファイルから各行を読み取る while ループ内で、単純な cout ステートメントを使用して行番号をコンソールに出力します。最近、私の友人の 1 人が、これによりコードが遅くなることを指摘しました。私はそれが本当かどうか疑問に思っていました、そしてそれはなぜですか?
3 に答える
すでに述べたように、端末への書き込みはほぼ間違いなく遅くなります。なんで?
- バッファリング:
端末への書き込みでは、line buffering
デフォルトで*が使用されます。これは、改行が検出されるたびにバッファの内容が送信されることを意味します。ファイルに書き込む場合、バッファがいっぱいになったとき、またはストリームを手動でフラッシュしたときにのみ、バッファがフラッシュされます。I / O操作の数が大幅に異なるため、これが違いの主な理由です。
*:これはUnix実装にも当てはまりますが、他の実装はバッファリングされない場合があります(コメントの説明を参照)。
- レンダリング:
端末に書き込む場合、これには画面でのレンダリングが含まれます。端末によっては、プログラムの速度を低下させる可能性のある他の操作が含まれる場合があります(すべての端末が同じになるわけではなく、に切り替えるだけで速度に大きな違いが生じる場合があります。別のもの)。
すでに述べたように、端末への書き込みはほぼ確実に遅くなります。なんで?
OS によっては、
std::cout
ライン バッファリングを使用する場合があります。これは、各ラインが端末プログラムに個別に送信される可能性があることを意味します。'\n' ではなく使用するstd::endl
と、確実にバッファがフラッシュされます。データを小さなチャンクで書き込むことは、余分なシステム コールとレンダリング作業を意味し、処理が大幅に遅くなります。一部のオペレーティング システム/コンパイラはさらに遅い - たとえば、Visual C++: https://connect.microsoft.com/VisualStudio/feedback/details/642876/std-wcout-is-ten-times-slower-than-wprintf-performance -bug-in-c-library
出力を表示する端末は、既存の画面コンテンツを消去し、フォントをレンダリングし、スクロール バーを更新し、行を履歴/バッファーにコピーするために呼び出しを行う必要があります。特に、新しいコンテンツを小さな断片で取得する場合、さらにどれくらい待たなければならないかを確実に推測することができず、受け取ったわずかな情報のために画面を更新しようとする可能性が高くなります。これにはコストがかかります。過剰なフラッシュまたはバッファリングされていない出力が遅い理由。
一部の端末では、「ジャンプ スクロール」のオプションが提供されています。つまり、10 ページ遅れていることがわかった場合、すぐに最後のページがレンダリングされ、それより前の 9 ページのコンテンツは画面に表示されません。これは便利で高速です。それでも、「ジャンプ スクロール」は、出力がエンド ユーザーの目に表示されないことを意味するため、常に使用または望まれるとは限りません。おそらく、プログラムは、場合によっては巨大な赤いエラー メッセージを出力することを意図しています。ユーザーの注意を引くためにちらつきますが、ジャンプスクロールがなければ、おそらく気付くでしょう。
私が Bloomberg で働いていたとき、ログ ファイルの更新が絶え間なく発生し、複数のモニターが占有されていました。表示される出力が数分遅れることもありました。デフォルトの Solaris xterm から rxvt への切り替えにより、常に対応できるようになりました
出力を /dev/null にリダイレクトすることは、特定の端末がどれだけ速度を落としているかを確認する良い方法です
それはほぼ間違いなく真実です。端末への書き込みは、物事を遅くすることで有名です。プログラムを実行し、出力をファイルにリダイレクトして、どれだけ高速かを確認してください。次に、出力ステートメントを完全に取り出して、再度測定します。すぐに挙動がわかります。
脳死の例を次に示します。
#include <stdio.h>
int main(void)
{
int i;
for (i = 0; i < 10000; i++)
{
printf("Hello, world!\n");
}
return 0;
}
このプログラムを最適化せずにビルドして実行しました。一度はターミナルに出力し、もう 1 度はファイルに出力しました。端末出力の結果:
real 0m0.026s
user 0m0.003s
sys 0m0.007s
リダイレクトされた I/O の結果:
real 0m0.003s
user 0m0.001s
sys 0m0.001s
これで、最大 8 倍速くなりました。そして、それは非常に少数の印刷のためです!