Ofstream 比 cout 更快吗?|| 存储比可视化输出更快?

3
出于某种原因,我决定制作一个非常简单的应用程序,显示从1到1000000的所有数字。我注意到显示结果比存储它们要花费更长的时间。我以为存储所有值需要比显示它们花费更长的时间。我还记得阅读过一篇文章,如果我没记错的话,在控制台应用程序中,用户输入和从文本文件中读取没有真正的区别,所以我认为显示和存储是一样的。 有人能解释一下这是为什么吗?根据我正在阅读的书中,ofstream 与 cout 非常相似,所以我不明白为什么它需要更长的时间。
为什么使用 cout 显示结果比使用 ofstream 将结果存储在文本文件中要慢?
cout = 169.168秒
ofstream = 3.473秒
ofstream 方法
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

namespace patch //used to patch some C++11 functions not included in mingw 4.7 // to_string
{
    template < typename T > std::string to_string( const T& n )
    {
        std::ostringstream stm ;
        stm << n ;
        return stm.str() ;
    }
}
using namespace patch;
using namespace std;

int main()
{
    int minimumRange = 1; //sets minimum number in range
    int maximumRange = 1000000; // sets maximum number in range
    string strRanges = to_string(minimumRange) + "-" + to_string(maximumRange); //appends string names
    ofstream myRange;
    myRange.open(strRanges + ".txt");

    for (int i = minimumRange; i<=maximumRange; ++i)
    {
        myRange << to_string(i) << "\n";
    }
   myRange.close();
    return 0;
}

cout method

#include <iostream>
using namespace std;

int main()
{
    int minimumRange = 1;
    int maximumRange = 1000000;
    for (int i = minimumRange; i<=maximumRange; ++i)
    {
        cout << i << "\n"; //using "/n" instead of endl; for speed purposes
    }
    return 0;
}

4
控制台/终端程序本身很慢。 - user2249683
也许系统会为您缓存文件,并异步将数据写入磁盘?对于您的文件版本,这将是简单的内存访问。向控制台写入受控制台速度限制(可能非常慢)的约束。 - user1781290
3
为了证明一点,尝试使用 std::cout 版本执行 ./program > /dev/null - user1508519
2
在测量 std::cout 的性能之前,请将其从 C 标准流中分离。参考链接:https://dev59.com/PV_Va4cB1Zd3GeqPWLy6#9026594 - dyp
1
@Ali myRange.open(strRanges + ".txt"); 是C++11(使用std::string打开文件)--只有在尝试编译它时才发现需要加上-std=c++11 ;) - dyp
显示剩余11条评论
1个回答

4
在许多系统上,cout只是一个映射到CON文件的ostream实例。它的目的是将支持的任何类型(主要是:const char*std::stringintlong ...,double ...)转换为要放置在缓冲区中的字符序列(请参见std::streambuf)。因此存储或输入操作是相同的。但是当缓冲区字符需要向物理设备输出时,就会涉及到设备驱动程序和相关的物理问题(主要是带宽、延迟和交错)。当操作系统传输大量数据到磁盘文件时,它使用一个驱动程序,该驱动程序可能内部使用缓存与使用通向控制器(位于磁盘上的微型计算机)的通信协议(主要是SATA、SCSI、NFS等)的外部设备进行通信。您的程序说“写入”,操作系统会告诉“已写入”,但是数据仍然在操作系统控制范围之外由设备控制器处理。这一部分与您异步发生。当您必须写入控制台时,大部分的这种“缓存”不能完成:只要您等待输入,cout就被刷新了(如果这是一个您必须回答的问题,您应该读取您写的内容)。因此,控制台驱动程序必须等待控制台程序完成其写入,然后才能继续进行。但是它的写入实际上是一种“绘画”:字符必须通过字体转换为像素,并且绘画必须与显示扫描同步(否则图像将被“干扰”)。这个过程比“写入磁盘”要慢(并且更长),后者实际上转化为“从进程移动大量内存到IO端口”(硬件可以通过交换两个指针寄存器来真正地执行此操作)。此外,控制台程序已经优化了数据要被看到(而使它比眼睛更快是没有意义的),而磁盘驱动程序则针对数据传输进行了优化。磁盘驱动程序比控制台程序更快是很正常的。

这对我来说很有道理,而且现在是凌晨3点。我没有考虑到控制台实际上是将结果绘制出来,或者它被优化为查看数据,而不是以用户无法理解的速度显示1-100万。是否可能创建一个优化的控制台或GUI,能够更及时地显示这些结果?我只是在假设,除非像QT或wxWidgets这样的东西更快,尽管我认为一个完整的GUI会更慢。 - Andrue
如果我知道接收设备很慢,而且唯一重要的是最后发送的数据,我可以预测“最后数据”何时发生,并避免打印永远不会被看到的内容... 这可能看起来很奇怪,但是一个完整的 GUI 可以比简单的控制台驱动程序更容易地意识到这一点(即使在恢复情况下也必须工作...所以我不能太复杂)。根据 GUI 的优化程度,它可能会显得更快。 但是这太具体实现了,不能再以一般形式讨论。 - Emilio Garavaglia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接