1

I always told that file io processes are the slowest ones. However when I test the two processes below:

Scenario 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();

Scenario 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();

I expect the senario1 to be slower because it does 1000 file io but test result showed that it has the same speed with scenario2 (in terms of clock_t). Why this is so, is it related with OS optimization as in file read? getline while reading a file vs reading whole file and then splitting based on newline character

Edited: With the advice of @irW

  string fileDataStr;

changed to

stringstream fileDataStr;
4

3 回答 3

3

由于std::ofstream缓冲输出的方式,您最终会在两种情况下执行完全相同数量的 IO。(通常,无论如何——当你输出一个很长的字符串时,一个实现可以优化事情。)唯一的区别是在第二种情况下,你引入了一个额外的中间缓冲区,这意味着更多的复制和一些更动态的分配。(多少动态分配取决于实现,但不应该太多。)

于 2013-10-02T08:52:32.347 回答
1

对此没有一个答案,因为结果会随着您使用的编译器和标准库而变化。例如,我将您的不同尝试放在一个带有一点测试/计时工具的程序中。然后,为了好玩,我添加了第四次尝试(下面代码中的 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

第四个版本(我添加的那个)使用 VC++ 的性能最差,但使用 g++ 的性能最好。使用 VC++ 仅次于最快的是(到目前为止)使用 g++ 最慢的。

你问为什么 X 是真的。不幸的是,X 并不总是正确的。

我们可能必须对您使用的确切编译器和标准库进行非常详细的分析,才能给出真正意义重大的答案。

于 2013-10-02T09:32:40.703 回答
1

每次您fileDataStr+=创建一个新字符串并将前一个字符串复制到其中时,字符串都是不可变的!如果您使用 astringstream它可能是一个更公平的比较。

于 2013-10-02T08:34:04.587 回答