ios_base :: sync_with_stdio(false)会影响<fstream>吗?

时间:2017-08-03 17:33:27

标签: c++11 fstream iostream cin cout

众所周知,ios_base::sync_with_stdio(false)将通过阻止同步b / w C和C ++ I / O来帮助<iostream>中cin和cout的性能。但是,我很好奇它是否在<fstream>中有任何不同。

我使用GNU C ++ 11和以下代码(使用和不使用ios_base::sync_with_stdio(false)代码段)运行了一些测试:

#include <fstream>
#include <iostream>
#include <chrono>
using namespace std;

ofstream out("out.txt");

int main() {
    auto start = chrono::high_resolution_clock::now();
    long long val = 2;
    long long x=1<<22;
    ios_base::sync_with_stdio(false);
    while (x--) {
        val += x%666;
        out << val << "\n";
    }
    auto end = chrono::high_resolution_clock::now();
    chrono::duration<double> diff = end-start;
    cout<<diff.count()<<" seconds\n";
  return 0;
}

结果如下:

With sync_with_stdio(false): 0.677863 seconds (average 3 trials)
Without sync_with_stdio(false): 0.653789 seconds (average 3 trials)

这是预期的吗?是否有理由使用sync_with_stdio(false)几乎相同(如果不是更慢)的速度?

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

sync_with_stdio() 的想法是允许将输入和输出混合到标准流对象(C 和 stdin 中的 stdoutstderrstd::cinstd::coutstd::cerrstd::clog 以及它们在 C++ 中对应的宽字符流),而无需担心字符会被缓冲在相关对象的任何缓冲区中。实际上,通过 std::ios_base::sync_with_stdio(true),C++ IOStreams 不能使用它们自己的缓冲区。在实践中,这通常意味着 std::streambuf 级别的缓冲完全被禁用。但是,没有缓冲区 IOStreams 相当昂贵,因为它们处理可能涉及多个虚拟函数调用的单个字符。本质上,您从 std::ios_base::sync_with_stdio(false) 获得的加速是允许 C 和 C++ 库使用自己的缓冲区。

另一种方法可能是在 C 和 C++ 库设施之间共享缓冲区,例如,通过在更强大的 C++ 库设施之上构建 C 库设施(在人们抱怨这将是一个糟糕的主意之前,使CI/O 更慢:如果正确实现标准 C++ 库 IOStreams,这实际上根本不是真的)。我不知道任何使用它的非实验性实现。使用此设置 std::ios_base::sync_with_stdio(value) 根本不会产生任何影响。

IOStreams 的典型实现为标准流对象使用不同的流缓冲区,而这些对象用于文件流。部分原因可能是标准流对象通常不是使用名称打开的,而是使用其他一些标识它们的实体打开的,例如,UNIX 系统上的文件描述符,它需要一个“后门”接口来允许使用 {{1 }} 用于标准流对象。然而,至少 Dinkumware 的标准 C++ 库的早期实现(例如,使用 MSVC++)使用 std::filebuf 作为标准流对象。这个 std::filebuf 实现只是 std::filebuf 的一个包装器,即,字面上实现了 C++ 标准所说的内容,而不是语义上的实现。一开始这已经是一个糟糕的想法,但是通过使用 FILE* 禁止所有文件流的 std::streambuf 级缓冲使情况变得更糟,因为该设置也会影响文件流。我不知道此 [性能] 问题是否已修复。 C/C++ 用户日志和/或 P.J.Plauger 的“[草案] 标准 C++ 库”中的旧问题应该显示对此实现的讨论。

tl;dr:根据标准 std::ios_base::sync_with_stdio(true) 仅更改标准流对象的约束以使其使用更快。它是否有其他影响取决于 IOStream 的实现,并且至少有一个(Dinkumware)发挥了作用。