我正在将小程序从PHP重写为C ++。这个想法基本上是通过SSD读取32Gb文件并对其进行一些简单的操作。
我正在使用带有x64版本构建的Visual Studio 2012。 PHP是5.3 32位。
问题是PHP中的裸读速度比C ++中的高,这真的让我感到困惑。 PHP大约350 Mb / s,C ++ / ifstream代码大约180 Mb /秒。
代码非常简单:
ifstream datafile("data.txt", ios::binary);
while(datafile.read((char*)buffer, data_per_chunk)) {
// do stuff;
我尝试过不同的缓冲区大小,最高可达16Mb,但差别不大。我也尝试通过datafile.rdbuf() - > pubsetbuf(...)设置内部缓冲区,但它也没有什么区别。
有没有关于如何在不恢复古老的C级界面的情况下加速ifstream的任何提示?我想至少达到PHP级别的性能。也许一些花哨的预读/缓存设置或其他东西。
据我所知,内存映射文件可能会有所帮助,但是如果可以保持简单,只要文件明显大于物理RAM且大于4Gb即可,那么它更愿意调整ifstream的设置。 -bit build。
答案 0 :(得分:3)
即使使用ifstream,您也可以达到最大的SSD读取速度。
为此,您需要将内部ifstream readbuffer设置为~2Mb,这是峰值SSD读取速度发生的地方,同时适合CPU的L2缓存。然后,您需要以小于内部缓冲区的块读出数据。我在8-16kB块中读取数据得到了最好的结果,但它比读取1Mb块的速度快了约1%。
设置ifstream内部缓冲区:
ifstream datafile("base.txt", ios::binary);
datafile.rdbuf()->pubsetbuf(iobuf, sizeof iobuf);
通过所有这些调整,我获得了495 Mb / sec的读取速度,接近M500 480Gb SSD的理论最大值。在执行期间,CPU负载为5%,这意味着它并未受到ifstream实现开销的限制。
我发现ifstream和std :: basic_filebuf之间没有可观察到的速度差异。
答案 1 :(得分:1)
当你将它全部读入缓冲区时,我没有看到使用ifstream
的意义。 basic_filebuf
或“古老”C接口都可以使用。您需要先将ifstream
与C接口进行比较,以便了解它真的是ifstream
的责任。
为了提高性能,我看到了以下选项:
std::ifstream
:read
等std::basic_filebuf
:open
,sgetn
等fopen
,fread
等CreateFile
(不 OpenFile
!),ReadFileEx
等。也许PHP没有在内部使用C接口,但是winapi,这就是差异的来源。