2

我正在将小程序从 PHP 重写为 C++。这个想法基本上是读取 SSD 上的 32Gb 文件并对其进行一些简单的操作。

我正在使用带有 x64 发行版的 Visual Studio 2012。PHP 是 5.3 32 位。

问题是 PHP 的读取速度比 C++ 高,这让我很困惑。PHP 约为 350 Mb/s,而 C++/ifstream 代码为 180 Mb/s。

代码真的很简单:

ifstream datafile("data.txt", ios::binary);

while(datafile.read((char*)buffer, data_per_chunk)) {
//  do stuff;

我尝试了不同的缓冲区大小,最大为 16Mb,但差别不大。我还尝试通过 datafile.rdbuf()->pubsetbuf(...) 设置内部缓冲区,但它也没有任何区别。

关于如何在不恢复到古老的 C 级接口的情况下加快 ifstream 的速度,是否有任何提示?我想至少达到 PHP 的性能水平。也许一些花哨的预读/缓存设置或其他东西。

我知道内存映射文件可能会有所帮助,但更愿意调整 ifstream 的设置,如果考虑到文件明显大于物理 RAM 且大于 4Gb 即不适合潜在的 32 位构建,则可以保持简单.

4

2 回答 2

5

即使使用 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/秒的读取速度,接近 M500 480Gb SSD 的理论最大值。在执行期间,CPU 负载为 5%,这意味着它并没有真正受到 ifstream 实现开销的限制。

我发现 ifstream 和 std::basic_filebuf 之间没有明显的速度差异。

于 2013-10-18T19:12:23.427 回答
1

ifstream当您将其全部读入缓冲区时,我看不到使用的意义。或者basic_filebuf“古老的”C 接口都可以工作。您需要先ifstream与C接口进行比较,以便您知道这确实ifstream是罪魁祸首。

我看到以下选项,以提高性能:

  • std::ifstream:read等。
  • std::basic_filebuf: open,sgetn
  • C : fopen,fread
  • WinApi:(不是!)CreateFile,等等。 OpenFileReadFileEx

或许PHP内部使用的不是C接口,而是winapi,这就是区别所在。

于 2013-10-18T02:27:51.683 回答