这是我到目前为止收集的内容:
缓冲:
如果默认情况下缓冲区非常小,增加缓冲区大小肯定可以提高性能:
可以通过访问底层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
语言环境意味着不执行任何转换以及在机器之间保持统一。这是一个很好的默认使用。
同步:
我看不到使用此工具的任何性能改进。
可以使用静态函数访问全局设置(的静态成员std::ios_base
) 。sync_with_stdio
测量:
玩这个,我玩弄了一个简单的程序,gcc 3.4.2
在 SUSE 10p3 上使用-O2
.
C : 7.76532e+06
C++: 1.0874e+07
20%
对于默认代码,这代表约 ... 的减速。实际上,篡改缓冲区(在 C 或 C++ 中)或同步参数 (C++) 并没有产生任何改进。
其他人的结果:
@Irfy 在 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 on 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 ram、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;
}