【发布时间】:2018-08-20 15:54:12
【问题描述】:
Stack Overflow 上的this answer 和cppreference.com 都建议关闭流同步以提高性能,认为流同步会禁用缓冲。
现在这是我不明白的。为什么同步流不能简单地共享缓冲区?我想象如果流是同步的,std::fputc(stdout, c); 可以简单地以std::cout << c; 或相反的方式(或使用通用原语)来实现。因此,当 C I/O 与 C++ I/O 混合时,同步流甚至比非同步流更有优势!更少的缓冲区,更少的缓存未命中。
当前的 C++ 标准草案似乎与我同在。在指定sync_with_stdio() 的脚注中,它说“实际上,同步通常意味着标准iostream 对象和标准stdio 对象共享一个缓冲区。”我在上面发布的链接是否可能只是记录了一些不完善的实现及其对性能的影响?
另外,因为我没有看到非同步流的任何理论上的缺点,我想知道为什么这些首先存在。
【问题讨论】:
-
附带说明,cppreference 建议
sync_with_stdio()影响标准流的线程安全。我认为这是完全错误的。 -
std::streambuf和支持stdio的任何缓冲区不能相同(它们具有不同的接口)。因此,根据我对链接的阅读,std::streambuf实现输出到 stdio 缓冲区,而本身不做任何缓冲。所以他们确实共享一个缓冲区,但 iostreams 有一个额外的间接层来获取它。此外,它们必须具有额外的线程锁定,以便通过 stdio 操作保持线程安全。 -
我不太明白。同步与否,两者共享同一个设备,必须始终相互独占访问。因此,一个同时保护 cin 和 stdin 的互斥体就足够了,不是吗?
-
好吧,
C++无法访问终极设备,这是 shell 的责任。但即便如此,在您到达设备之前,您拥有共享缓冲区,该缓冲区需要 stdio 和 iostream 之间的互斥体。我想他们可以为此共享一个互斥锁,但这会将两个库非常紧密地耦合在一起,我不知道那里有什么恶魔。无论如何,我认为 iostream 可能必须拥有自己的独立锁定才能在所有 streams 中履行其线程安全义务,而不仅仅是cin/cout。所以我怀疑它必须锁定 两个 互斥锁才能与 stdio 同步。 -
@purefanatic
sync_with_stdio()会影响eel.is/c++draft/iostream.objects#overview-5 中指定的标准流的线程安全