大多数学习 C 的 C++ 用户更喜欢使用 printf
/scanf
系列函数,即使他们使用 C++ 编码。
虽然我承认我发现界面更好(尤其是类似 POSIX 的格式和本地化),但似乎压倒性的关注是性能。
看看这个问题:
似乎最好的答案是使用 fscanf
并且 C++ ifstream
始终慢 2-3 倍。
我认为如果我们可以编译一个“技巧”存储库来提高 IOStreams 的性能,什么有效,什么无效,那就太好了。
需要考虑的要点
rdbuf()->pubsetbuf(buffer, size)
) std::ios_base::sync_with_stdio
)当然,也欢迎其他方法。
注意:提到了 Dietmar Kuhl 的"new"实现,但我无法找到有关它的许多细节。以前的引用文献似乎是死链接。
最佳答案
以下是我到目前为止收集的内容:
缓冲 :
如果默认情况下缓冲区很小,增加缓冲区大小肯定可以提高性能:
可以通过访问底层
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
的静态成员)。测量值:
玩这个,我玩弄了一个简单的程序,在 SUSE 10p3 上使用
gcc 3.4.2
和 -O2
编译。对于默认代码,这代表了大约
20%
... 的减速。实际上,篡改缓冲区(在 C 或 C++ 中)或同步参数 (C++) 并没有产生任何改进。其他人的结果:
C++ 快 25%
C++ 快 17%
C++ 慢 111%
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;
}
关于c++ - 如何让 IOStream 表现得更好?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5166263/