9

テキストを標準出力に出力するさまざまな方法の違いを計っています。をテストしてcoutおりprintf、 とostringstreamの両方\nを使用していstd::endlます。私std::endlは違いを生むことを期待していましたがcout(実際にそうでした)、出力が遅くなるとは思っていませんでしたostringstreamstd::endlusingはストリームに a を書き込むだけで、\n一度だけフラッシュされると思いました。何が起きてる?ここにすべての私のコードがあります:

// cout.cpp
#include <iostream>

using namespace std;

int main() {
  for (int i = 0; i < 10000000; i++) {
    cout << "Hello World!\n";
  }
  return 0;
}

// printf.cpp
#include <stdio.h>

int main() {
  for (int i = 0; i < 10000000; i++) {
    printf("Hello World!\n");
  }
  return 0;
}

// stream.cpp
#include <iostream>
#include <sstream>

using namespace std;

int main () {
  ostringstream ss;
  for (int i = 0; i < 10000000; i++) {
    ss << "stream" << endl;
  }
  cout << ss.str();
}

// streamn.cpp
#include <iostream>
#include <sstream>

using namespace std;

int main () {
  ostringstream ss;
  for (int i = 0; i < 10000000; i++) {
    ss << "stream\n";
  }
  cout << ss.str();
}

そして、これが私のMakefileです

SHELL:=/bin/bash

all: cout.cpp printf.cpp
    g++ cout.cpp -o cout.out
    g++ printf.cpp -o printf.out
    g++ stream.cpp -o stream.out
    g++ streamn.cpp -o streamn.out
time:
    time ./cout.out > output.txt
    time ./printf.out > output.txt
    time ./stream.out > output.txt
    time ./streamn.out > output.txt

makeこれが私が実行したときに得られるものですmake time

time ./cout.out > output.txt

real    0m1.771s
user    0m0.616s
sys 0m0.148s
time ./printf.out > output.txt

real    0m2.411s
user    0m0.392s
sys 0m0.172s
time ./stream.out > output.txt

real    0m2.048s
user    0m0.632s
sys 0m0.220s
time ./streamn.out > output.txt

real    0m1.742s
user    0m0.404s
sys 0m0.200s

これらの結果は一貫しています。

4

3 に答える 3

14

std::endlストリームのフラッシュがトリガーされ、印刷が大幅に遅くなります。http://en.cppreference.com/w/cpp/io/manip/endlを参照してください。

std::endlストリームを本当にフラッシュしたい場合を除き、使用しないことをお勧めします。これが本当に重要かどうかは、ユースケースによって異なります。

ostringstream でもパフォーマンスに影響を与える理由flush(フラッシュが発生しない場合) について: 少なくともセントリー オブジェクトを構築するには実装が必要なようです。goodそれらはとtieのをチェックする必要がありostreamます。への呼び出しはpubsync最適化できるはずです。これは、私の libcpp と libstdc++ の読みに基づいています。

もう少し読んだ後、興味深い質問は次のようです:basic_ostringstream::flush歩哨オブジェクトを構築するために本当に必要な実装はありますか? そうでない場合、これは「実装の品質」の問題のように思えます。しかし、実際には必要だと思いbasic_stringbugますbadbit

于 2012-10-01T14:31:35.120 に答える
1

ストリームの各出力操作は、複数の手順を実行します。

  • ストリームの状態が良好かどうかをチェックします。
  • 他のストリームをフラッシュする必要があるかどうかを確認します。
  • 文字のシーケンスが生成されます。
  • 書かれた文字に十分なスペースがあるかどうかをチェックします。
  • を使用するとendl、ストリーム バッファーで追加の仮想関数が呼び出されます。

個人的には、追加の仮想関数呼び出しが実際に与える影響は、他の操作に比べて比較的小さいと予想しています。この出力をプロファイリングすることで、この推測を確認できます。

out << "stream" << '\n';

... あるいは

out << "stream" << out.widen('\n');

とはいえ、チェックを削減するためにストリームの実装に適用できる多くの改善点があります。もちろん、これが行われるかどうかは実装に依存します。

于 2012-10-01T17:27:40.717 に答える
0

使用std::endlすることは、書くことと同等です

stream << "\n";
stream.flush();

std::endl実際にフラッシュをトリガーしたい場合、および/または出力パフォーマンスを気にしない場合を除き、使用しないでください。

また、異なるプラットフォームで異なる行末について心配する必要はありません。実装は"\n"、プラットフォームに適した行末に変換されます。

于 2012-10-01T14:34:59.777 に答える