PHP 是否将连续的 fseek 命令静默优化为一个 fseek 命令?

Does PHP silently optimize consecutive fseek-commands into one fseek command?

我是 运行 Windows 7 - 64 位,最新的 XAMPP 版本有 32 位 PHP 版本。

测试中http://php.net/manual/en/function.fseek.php#112647 对于一个非常大的文件(大于 PHP_MAX_INT 2147483647),我现在很确定,在文件指针上执行之前,连续跟随的 fseeks 被汇总。

我有两个问题:

  1. 我能否以合理的方式(或仅使用上面 link 中提到的解决方法)打破这个总结?

  2. 这种聚合是发生在 PHP 中(正如我假设的那样,尽管我不知道 PHP 中的哪个位置)还是 Windows 7 中?

Answering myself: Trying two workarounds with multiple seeks didn't work on my system. Instead they put the filepointer to different positions at under PHP_MAX_INT. (32-bit PHP only can seek up to PHP_MAX_INT + 8192. Reading from there on is still possible, but I don't know how far.)

Therefore the question is obsolete for my specific case, as 32-bit PHP only can seek up to PHP_MAX_INT + 8192, whatever you do. I leave the question, because two people voted it up, and might be interested in a general answer.

我在这里提交了错误报告:
https://bugs.php.net/bug.php?id=69213
结果:使用 64 位 PHP 构建它可能会工作,但我没有尝试。

没有。它实际上做了一些 甚至更笨的事情。 这是 PHP 源代码的片段:

      switch(whence) {
          case SEEK_CUR:
              offset = stream->position + offset;
              whence = SEEK_SET;
              break;
      }

这是 PHP 的 fseek 实现的核心。这里发生的事情是:如果您告诉 PHP 从当前位置开始查找,它会将其转换为 "equivalent" 从文件开头查找。这仅在偏移计算没有溢出时有效;如果是,那么 offset 是一个带符号的整数,所以这是未定义的行为。

而且,好吧,这是因为 PHP 在内部缓冲流,所以他们需要做一些 事情。 但不一定非要这样。

您可能最好尝试使用一种真正按照您的要求进行操作的语言来完成您的工作。

如果要发生聚合,则可能必须作为操作码优化,或者必须通过缓冲区在低级别发生。

我可以低水平回答。 php 中的 fseek() 是使用 php 流实现的。它在 ext/standard/file.h 中声明并在 .c 中定义。它的实现调用 php_stream_seek(),它调用 streams.c 中的 _php_stream_seek()。这个的低级实现是通过普通流包装器处理的,在这种情况下,通过 zend_seek 或 zend_fseek 寻求调用,这反过来只是映射到 32 位或 64 位 seek _seeki64 c 调用。

所以...如果发生任何聚合,它似乎必须在操作码优化中,甚至在 OS 或硬件中更进一步。硬盘实现乱序获取以减少磁头寻道距离,文件系统缓冲系统可能能够减少没有副作用的寻道。如果您担心磁盘读取时间,第一个会自动处理。如果您担心可能会影响内存(在缓冲区中不必要地寻找很远的距离),您可能会考虑另一种方法。有关磁盘如何避免浪费寻道时间的更多信息,请参阅:http://www.cs.iit.edu/~cs561/cs450/disksched/disksched.html

希望对您有所帮助。