【发布时间】:2014-11-23 13:35:24
【问题描述】:
我正在研究一个简单的解析器,在分析时我观察到瓶颈在于...文件读取!我提取了一个非常简单的测试来比较fstreams 和FILE* 在读取大量数据时的性能:
#include <stdio.h>
#include <chrono>
#include <fstream>
#include <iostream>
#include <functional>
void measure(const std::string& test, std::function<void()> function)
{
auto start_time = std::chrono::high_resolution_clock::now();
function();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - start_time);
std::cout<<test<<" "<<static_cast<double>(duration.count()) * 0.000001<<" ms"<<std::endl;
}
#define BUFFER_SIZE (1024 * 1024 * 1024)
int main(int argc, const char * argv[])
{
auto buffer = new char[BUFFER_SIZE];
memset(buffer, 123, BUFFER_SIZE);
measure("FILE* write", [buffer]()
{
FILE* file = fopen("test_file_write", "wb");
fwrite(buffer, 1, BUFFER_SIZE, file);
fclose(file);
});
measure("FILE* read", [buffer]()
{
FILE* file = fopen("test_file_read", "rb");
fread(buffer, 1, BUFFER_SIZE, file);
fclose(file);
});
measure("fstream write", [buffer]()
{
std::ofstream stream("test_stream_write", std::ios::binary);
stream.write(buffer, BUFFER_SIZE);
});
measure("fstream read", [buffer]()
{
std::ifstream stream("test_stream_read", std::ios::binary);
stream.read(buffer, BUFFER_SIZE);
});
delete[] buffer;
}
在我的机器上运行这段代码的结果是:
FILE* write 1388.59 ms
FILE* read 1292.51 ms
fstream write 3105.38 ms
fstream read 3319.82 ms
fstream 写/读比FILE* 写/读慢大约 2 倍!这在读取大量数据时,没有任何解析或fstreams 的其他功能。我在 Mac OS、Intel I7 2.6GHz、16GB 1600 MHz Ram、SSD 驱动器上运行代码。请注意,再次运行相同的代码FILE* read 的时间非常短(大约 200 毫秒),可能是因为文件被缓存了......这就是为什么打开读取的文件不是使用代码创建的。
与FILE*相比,为什么使用fstream 仅读取一个二进制数据的速度如此之慢?
编辑 1: 我更新了代码和时间。抱歉耽搁了!
编辑 2:我添加了命令行和新结果(与以前的结果非常相似!)
$ clang++ main.cpp -std=c++11 -stdlib=libc++ -O3
$ ./a.out
FILE* write 1417.9 ms
FILE* read 1292.59 ms
fstream write 3214.02 ms
fstream read 3052.56 ms
根据第二次运行的结果:
$ ./a.out
FILE* write 1428.98 ms
FILE* read 196.902 ms
fstream write 3343.69 ms
fstream read 2285.93 ms
在读取 FILE* 和 stream 时,文件似乎被缓存了,因为它们的时间减少了相同的数量。
编辑 3: 我将代码简化为:
FILE* file = fopen("test_file_write", "wb");
fwrite(buffer, 1, BUFFER_SIZE, file);
fclose(file);
std::ofstream stream("test_stream_write", std::ios::binary);
stream.write(buffer, BUFFER_SIZE);
并启动分析器。似乎stream 在xsputn 函数中花费了大量时间,而实际的write 调用具有相同的持续时间(应该是,它是相同的函数......)
Running Time Self Symbol Name
3266.0ms 66.9% 0,0 std::__1::basic_ostream<char, std::__1::char_traits<char> >::write(char const*, long)
3265.0ms 66.9% 2145,0 std::__1::basic_streambuf<char, std::__1::char_traits<char> >::xsputn(char const*, long)
1120.0ms 22.9% 7,0 std::__1::basic_filebuf<char, std::__1::char_traits<char> >::overflow(int)
1112.0ms 22.7% 2,0 fwrite
1127.0ms 23.0% 0,0 fwrite
EDIT 4 出于某种原因,此问题被标记为重复。我想指出我根本不用printf,我只用std::cout来写时间。 read 部分中使用的文件是write 部分的输出,使用不同的名称复制以避免缓存
【问题讨论】:
-
什么操作系统,什么编译器设置?
-
这不能回答您的问题,但请记住,在具有相同磁盘缓存的操作系统(例如 Linux)上,您的结果将严重偏斜(您无法直接从 HDD 读取 1GB例如,在 200 毫秒内。)
-
你的前两个
measures 不应该是至少fclose和FILE *吗? -
@rapptz - 如果你每秒只能构造 10 个字符串流,那你的日子会很悲惨!
标签: c++ performance