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. 我可以用合理的方法(或仅使用上面链接中提到的解决方法)来分解这个总结吗?

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

回答自己:尝试两种具有多个搜索的解决方法不起作用 在我的系统上。相反,他们将文件指针放在不同的位置 PHP_MAX_INT(32 位 PHP 最多只能寻求 PHP_MAX_INT + 8192.从那里开始阅读仍然是可能的,但我不知道有多远。

因此,对于我的具体情况,这个问题已经过时了,因为 32 位 PHP 最多只能寻求 PHP_MAX_INT + 8192,无论您做什么。我 留下这个问题,因为有两个人投票赞成,而且可能是 对一般答案感兴趣。

我在这里提交了错误报告:

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 从当前位置进行查找,它会将其转换为从文件开头开始的"等效"查找。这仅在偏移量计算不会溢出时才有效;如果是这样,那么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 调用。

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

我希望这有所帮助。