是PHP';s哈希_文件内部流?

是PHP';s哈希_文件内部流?,php,Php,我注意到,当我在一个大文件(5GB)上调用hash_file时,我的机器的内存使用量大大增加。操作成功完成,但我想知道hash\u file的内部实现是将文件内容流式传输到哈希算法中,还是尝试先将整个文件内容加载到内存中。有人知道吗?它将整个内容映射到虚拟内存中。整个内容必须在物理内存中才能执行哈希操作,但不能同时执行所有内容。与往常一样,机器的物理内存包含映射到虚拟内存的部分内容,由操作系统管理以最有效地利用物理内存 仔细想想,为了计算散列,文件的所有内容在某个点通过物理内存基本上是不可避免的

我注意到,当我在一个大文件(5GB)上调用
hash_file
时,我的机器的内存使用量大大增加。操作成功完成,但我想知道
hash\u file
的内部实现是将文件内容流式传输到哈希算法中,还是尝试先将整个文件内容加载到内存中。有人知道吗?

它将整个内容映射到虚拟内存中。整个内容必须在物理内存中才能执行哈希操作,但不能同时执行所有内容。与往常一样,机器的物理内存包含映射到虚拟内存的部分内容,由操作系统管理以最有效地利用物理内存

仔细想想,为了计算散列,文件的所有内容在某个点通过物理内存基本上是不可避免的。文件的每个字节都必须由CPU处理以产生散列,因此,如果尚未在内存中,则必须读取。如果有足够的物理内存,您可能希望它留在那里,因为一个常见的模式是在散列后再次读取同一个文件


如果散列一个比物理内存大的文件,那么在读取新数据时,必须丢弃一些数据。操作系统通过调整物理内存中实际驻留的虚拟内存页来管理这一点。包含文件系统中仍然可用的干净数据副本的页面可以从物理内存和用于保存新读取信息的物理内存中轻松地丢弃。

还没有人正确回答这个问题,所以我要回答我自己的问题。经过一点测试,结果表明,
hash\u file
确实以流的形式对文件进行操作,而不是在内部使用一些愚蠢的东西,如
file\u get\u contents
。通过使用
php\u memory\u limit
值低于被散列文件大小的环境进行测试。(首先应该这样做,抱歉吵闹。)

哈希不能按顺序进行。每个字符都会完全更改最终散列。您可以先对文件进行gzip,但每次比较哈希值时都需要这样做。@Anthony:绝对不正确。目前使用的绝大多数散列函数都是增量计算的;它们只是在块的基础上操作,并使用一个终结步骤,这使得不可能将数据附加到“完成的”散列中。不过,它们在内部是完全连续的。对于小数据散列也是如此吗,比如10个字符密码上的sha256?@Anthony Yes。散列操作本质上是流操作。不需要为了计算散列而将整个文件加载到虚拟内存中;该算法保持一定量的内部状态,并可在流结束时的任何时间最终确定。您可以以完全相同的方式散列>=0的任意字节数,并在流的末尾留出一些填充空间。我只是想问PHP在这方面是否聪明,因为文档中没有提到。这个答案有很多错误。首先,哈希算法总是在流上运行。不需要在虚拟内存中保留比当前流式传输到算法的块更多的页面。“如果有足够的物理内存,您可能希望它留在那里,因为一种常见的模式是在对同一文件进行哈希运算后再次读取该文件。”磁盘中的页面将留在物理内存LRU缓存中,但将整个文件读入虚拟内存以计算校验和是完全愚蠢的。读了几遍之后,发现它确实是内部流的。@zjm555您所说的与我的答案中的任何内容都不一致。我从未说过有必要将数据保存在物理内存中,只是如果有足够的物理内存可用,那么这样做是有意义的。(因为数据可能很快就会被用来对抗。而且你可以在以后扔掉它。不必急于扔掉那些可能有用的信息,因为保留这些信息的成本为零。)“如果你散列了一个比物理内存大的文件,那么在读取新数据时,一些数据将不得不被丢弃。”这听起来好像整个文件一次都在内存中。实际上,在流式传输散列时,您将一次从文件中读取一些固定大小的块(通常是KB,可能是MB),这就是您所需要的全部内存。每次从流中读取时,都会覆盖固定大小的缓冲区。磁盘控制器或操作系统实现磁盘块缓存和实现
hash_file
@zjm555的问题完全无关。再说一次,你们并没有不同意我的观点。问题不在于你需要什么样的记忆,而在于你实际使用了什么样的记忆。如果有足够的物理内存,那么大部分数据将立即存储在内存中。但是,有一点是错误的——问题不是磁盘块缓存,而是虚拟页面缓存。磁盘块缓存基本上已经不存在了——现代操作系统有一个统一的页面缓存。是的,在实际情况下,它会占用大量内存。是的,它也可以用更少的内存工作。你有+5GB的内存分配给php吗?如果您关心性能,您应该调整开发环境,以获得更好的“自然”性能。否。我刚刚验证了它小于5GB,这证明它没有加载整个文件。我经历的内存膨胀与
hash\u文件的调用无关。好吧,不要让我们悬而未决!根本原因是什么?完全来自另一个过程:)