2013-10-02 82 views
1

我总是告诉文件io进程是最慢的。然而,当我测试下面的两个过程:一次写入文件,一次写入全文

方案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(); 

我希望,因为它1000文件IO的senario1要慢一些,但测试结果显示它与情景2具有相同的速度(以clock_t表示)。为什么这样,它是否与文件读取中的操作系统优化相关? getline while reading a file vs reading whole file and then splitting based on newline character

编辑:随着@irW

建议
string fileDataStr; 

改为

stringstream fileDataStr; 
+0

很明显,因为字符串处理正在进入图片,导致几个分配等 – P0W

+0

我想在同等条件下做这个测试。我可以用指针而不是使用字符串连接来实现这一点,还是有其他方法? – aldebaran

回答

3

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

+0

std :: ofstream缓冲区输出,并当我冲洗或关闭文件时(?) – aldebaran

+0

@platon或当缓冲区已满时执行文件io。 –

1

每次有fileDataStr+=你是一个新的字符串和复制以前的一成多吧,弦是不可改变的!如果您使用stringstream这可能是一个更公平的比较。

+0

非常感谢。现在两种情况给出了相同的结果(我相应地改变了问题)。你有这个想法吗?为什么stringstream不是更快? – aldebaran

+0

使用'std :: ostringstream'可能不会改变任何东西;最有可能的是,它最终会在引擎盖下做同样的“+ =”。 (当然,它可以使用某种内部缓冲,所以它会少一些,但是通常'std :: ostringstream'会更慢,因为它会附加到流中。) –

+0

我的猜测是你的输出fstream可能会做一些缓冲? (不确定是否应该查看它)接下来,stringstream可能在内部作为字符数组进行管理,并且在一段时间内调整大小(与Java中的StringBuilder一样),这也会导致开销。您可以通过保留足够的空间来消除后者:'str.reserve(buffersize);' – DDW

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并不总是如此。

我们可能需要对确切的编译器和标准库进行相当详细的分析,以便给出一个真正意义重大的答案。