1

私はいつも、ファイル io プロセスが最も遅いプロセスだと言いました。ただし、以下の2つのプロセスをテストすると:

シナリオ 1:

test.open("test.xml",fstream::out);
for(int i=0;i<1000;i++)
{
    test<<"<p> attr1=\"test1\" attr2=\"test2\" attr3=\"test3\" attr4=\"test4\">test5</p>\n";
}
test.close();

シナリオ 2:

test.open("test.xml",fstream::out);
stringstream fileDataStr;
for(int i=0;i<1000;i++)
{
    fileDataStr<<"<p> attr1=\"test1\" attr2=\"test2\" attr3=\"test3\" attr4=\"test4\">test5</p>\n";
}
test<<fileDataStr;
test.close();

senario1 は 1000 個のファイル io を実行するため、遅くなると予想されますが、テスト結果では、cenario2 と同じ速度であることが示されました (clock_t に関して)。これはなぜそうなのか、ファイルの読み取りのように OS の最適化に関係しているのですか? ファイルの読み取り中の getline とファイル全体の読み取りと、改行文字に基づく分割

編集: @irW のアドバイスを受けて

  string fileDataStr;

に変更

stringstream fileDataStr;
4

3 に答える 3

3

バッファ出力の方法によりstd::ofstream、どちらの場合もまったく同じ量の IO を実行することになります。(通常、いずれにせよ、非常に長い文字列を出力する場合、実装によって最適化できます。) 唯一の違いは、2 番目のケースでは追加の中間バッファーを導入したことです。より動的な割り当て。(動的割り当ての数は実装によって異なりますが、多すぎてはいけません。)

于 2013-10-02T08:52:32.347 に答える
1

これに対する答えは 1 つではありません。使用するコンパイラや標準ライブラリによって結果が異なる可能性があるためです。たとえば、小さなテスト/タイミング ハーネスを使用して、さまざまな試みを 1 つのプログラムにまとめました。次に、楽しみのために、4 回目の試行 (以下のコードの test3) を追加しました。

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <time.h>
#include <fstream>
#include <sstream>
#include <string.h>

static const int limit = 1000000;

void test1() {
    std::ofstream test("test.xml");
    for (int i = 0; i < limit; i++)
    {
        test << "<p> attr1=\"test1\" attr2=\"test2\" attr3=\"test3\" attr4=\"test4\">test5</p>\n";
    }
    test.close();
}

void test11() {
    std::ofstream test("test.xml");
    std::string fileDataStr;
    for (int i = 0; i < limit; i++)
    {
        fileDataStr += "<p> attr1=\"test1\" attr2=\"test2\" attr3=\"test3\" attr4=\"test4\">test5</p>\n";
    }
    test << fileDataStr;
    test.close();

}
void test2() {
    std::ofstream test("test.xml");
    std::stringstream fileDataStr;
    for (int i = 0; i < limit; i++)
    {
        fileDataStr << "<p> attr1=\"test1\" attr2=\"test2\" attr3=\"test3\" attr4=\"test4\">test5</p>\n";
    }
    test << fileDataStr.str();
    test.close();
}

void test3() {
    std::ofstream test("test.xml");
    std::vector<char> buffer;
    char line [] = "<p> attr1=\"test1\" attr2=\"test2\" attr3=\"test3\" attr4=\"test4\">test5</p>\n";
    size_t len = strlen(line);

    buffer.reserve(limit * len + 1);

    for (int i = 0; i < limit; i++)
        std::copy(line, line + len, std::back_inserter(buffer));

    test.write(&buffer[0], buffer.size());
    test.close();
}

template <class T>
void timer(T f) {
    clock_t start = clock();
    f();
    clock_t stop = clock();
    std::cout << double(stop - start) / CLOCKS_PER_SEC << " seconds\n";
}

int main() {
    timer(test1);
    timer(test11);
    timer(test2);
    timer(test3);
}

次に、VC++ でコンパイルしたところ、次の結果が得られました。

0.681 seconds
0.659 seconds
0.874 seconds
0.955 seconds

次に、g++ でコンパイルしたところ、次の結果が得られました。

1.267 seconds
0.725 seconds
0.795 seconds
0.649 seconds

4 番目のバージョン (私が追加したもの) では、VC++ で最悪のパフォーマンスが得られますが、g++ で最高のパフォーマンスが得られます。VC++ で 2 番目に高速だったものは、(はるかに) g++ で最も低速です。

Xが真である理由を尋ねています。残念ながら、X は常に真であるとは限りません。

本当に意味のある答えを出すには、あなたが使用していた正確なコンパイラと標準ライブラリのかなり詳細な分析を行う必要があるでしょう。

于 2013-10-02T09:32:40.703 に答える
1

fileDataStr+=新しい文字列を作成して前の文字列をコピーするたびに、文字列は不変です! a を使用する場合はstringstream、より公平な比較になる可能性があります。

于 2013-10-02T08:34:04.587 に答える