这是我目前收集到的:
缓冲:
如果默认情况下缓冲区很小,增加缓冲区大小肯定可以提高性能:
- 它减少了 HDD 命中次数
- 它减少了系统调用的次数
可以通过访问底层的streambuf 实现来设置缓冲区。
char Buffer[N];
std::ifstream file("file.txt");
file.rdbuf()->pubsetbuf(Buffer, N);
// the pointer reader by rdbuf is guaranteed
// to be non-null after successful constructor
@iavr 的警告:根据cppreference,最好在打开文件之前致电pubsetbuf。不同的标准库实现有不同的行为。
区域设置处理:
Locale 可以在涉及数字或日期的情况下执行字符转换、过滤和更巧妙的技巧。它们经历了一个由动态调度和虚拟调用组成的复杂系统,因此移除它们有助于减少惩罚。
默认的C 语言环境意味着不执行任何转换以及在机器之间保持统一。这是一个很好的默认值。
同步:
我看不到使用此工具的任何性能改进。
可以使用sync_with_stdio 静态函数访问全局 设置(std::ios_base 的静态成员)。
测量:
玩这个,我玩弄了一个简单的程序,在 SUSE 10p3 上使用gcc 3.4.2 和-O2 编译。
C : 7.76532e+06
C++:1.0874e+07
对于默认代码,这代表大约 20%... 的减速。实际上,篡改缓冲区(在 C 或 C++ 中)或同步参数 (C++) 并没有产生任何改进。
其他人的结果:
@Irfy on g++ 4.7.2-2ubuntu1、-O3、虚拟化 Ubuntu 11.10、3.5.0-25-generic、x86_64、足够的 ram/cpu、196MB 的几个“find / >> largefile.txt”运行
C : 634572
C++:473222
C++ 快 25%
@Matteo Italia 在 g++ 4.4.5、-O3、Ubuntu Linux 10.10 x86_64 上使用随机 180 MB 文件
C : 910390
C++:776016
C++ 快 17%
@Bogatyr 在 g++ i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1(Apple Inc. build 5664)上,mac mini,4GB ram,除此测试外空闲,数据文件为 168MB
C : 4.34151e+06
C++:9.14476e+06
C++ 慢 111%
@Asu on clang++ 3.8.0-2ubuntu4、Kubuntu 16.04 Linux 4.8-rc3、8GB 内存、i5 Haswell、Crucial SSD、88MB 数据文件(tar.xz 存档)
C : 270895
C++:162799
C++ 快 66%
所以答案是:这是一个实施质量问题,实际上取决于平台:/
此处为对基准测试感兴趣的人提供的完整代码:
#include <fstream>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <sys/time.h>
template <typename Func>
double benchmark(Func f, size_t iterations)
{
f();
timeval a, b;
gettimeofday(&a, 0);
for (; iterations --> 0;)
{
f();
}
gettimeofday(&b, 0);
return (b.tv_sec * (unsigned int)1e6 + b.tv_usec) -
(a.tv_sec * (unsigned int)1e6 + a.tv_usec);
}
struct CRead
{
CRead(char const* filename): _filename(filename) {}
void operator()() {
FILE* file = fopen(_filename, "r");
int count = 0;
while ( fscanf(file,"%s", _buffer) == 1 ) { ++count; }
fclose(file);
}
char const* _filename;
char _buffer[1024];
};
struct CppRead
{
CppRead(char const* filename): _filename(filename), _buffer() {}
enum { BufferSize = 16184 };
void operator()() {
std::ifstream file(_filename, std::ifstream::in);
// comment to remove extended buffer
file.rdbuf()->pubsetbuf(_buffer, BufferSize);
int count = 0;
std::string s;
while ( file >> s ) { ++count; }
}
char const* _filename;
char _buffer[BufferSize];
};
int main(int argc, char* argv[])
{
size_t iterations = 1;
if (argc > 1) { iterations = atoi(argv[1]); }
char const* oldLocale = setlocale(LC_ALL,"C");
if (strcmp(oldLocale, "C") != 0) {
std::cout << "Replaced old locale '" << oldLocale << "' by 'C'\n";
}
char const* filename = "largefile.txt";
CRead cread(filename);
CppRead cppread(filename);
// comment to use the default setting
bool oldSyncSetting = std::ios_base::sync_with_stdio(false);
double ctime = benchmark(cread, iterations);
double cpptime = benchmark(cppread, iterations);
// comment if oldSyncSetting's declaration is commented
std::ios_base::sync_with_stdio(oldSyncSetting);
std::cout << "C : " << ctime << "\n"
"C++: " << cpptime << "\n";
return 0;
}