fprintf 与 std::ofstream 的性能非常令人惊讶(fprintf 非常慢)

问题描述 投票:0回答:5

我正在运行一些基准测试,以找到在 C++ 中将大型数组写入文件的最有效方法(在 ASCII 中超过 1Go)。

所以我将 std::ofstream 与 fprintf 进行了比较(请参阅下面我使用的开关)

    case 0: {
        std::ofstream out(title, std::ios::out | std::ios::trunc);
        if (out) {
            ok = true;
            for (i=0; i<M; i++) {
                for (j=0; j<N; j++) {
                    out<<A[i][j]<<" ";
                }
                out<<"\n";
            }
            out.close();
        } else {
            std::cout<<"Error with file : "<<title<<"\n";
        }
        break;
    }
    case 1: {
        FILE *out = fopen(title.c_str(), "w");
        if (out!=NULL) {
            ok = true;
            for (i=0; i<M; i++) {
                for (j=0; j<N; j++) {
                    fprintf(out, "%d ", A[i][j]);
                }
                fprintf(out, "\n");
            }
            fclose(out);
        } else {
            std::cout<<"Error with file : "<<title<<"\n";
        }
        break;
    }

我的一个大问题是,与 std::ofstream 相比,fprintf 似乎慢了 12 倍以上。您知道我的代码中问题的根源是什么吗?或者也许 std::ofstream 与 fprintf 相比非常优化?

(还有另一个问题:你知道另一种更快的写入文件的方法吗)

非常感谢

(详细信息:我正在使用 g++ -Wall -O3 进行编译)

c++ ofstream printf
5个回答
18
投票

fprintf("%d"
需要对格式字符串进行运行时解析,每个整数一次。
ostream& operator<<(ostream&, int)
由编译器解析,每次编译一次。


4
投票

好吧,

fprintf()
确实需要在运行时做更多的工作,因为它必须解析和处理格式字符串。但是,考虑到输出文件的大小,我预计这些差异影响不大,并且预计代码受 I/O 限制。

因此,我怀疑您的基准在某种程度上存在缺陷。

  1. 如果重复运行测试,您是否始终会得到 12 倍的差异?
  2. 如果颠倒运行测试的顺序,时间会发生什么变化?
  3. 如果您最后调用
    fsync()/sync()
    会发生什么?

2
投票

ofstream中有一个文件缓冲区,这可以减少访问磁盘的次数。另外,fprintf是一个可变参数的函数,它会调用一些va_#函数,但ofstream不会。我认为你可以使用fwrite()或putc()进行测试。


1
投票

您是否在所显示的代码上游的某个位置设置了sync_with_stdio?

虽然您报告的内容与经验所见相反,但大多数人认为并相信您所看到的应该是常态。 iostream 是类型安全的,而 printf 系列函数是可变参数函数,必须从格式说明符推断 va_list 的类型。


0
投票

怎么样:

uint32_t foo;
// <some code setting foo>
std::cout<< std::setfill('0') << std::setw(8) << foo << std<<endl;

编译器无法解析它。

© www.soinside.com 2019 - 2024. All rights reserved.