方法概述
在互联网上搜索,我遇到了不同的解决方案。我可以把他们分组
在三种方法:
>天真的那些使用file()PHP函数;
>在系统上运行尾命令的欺骗;
>强大的,使用fseek()快乐地跳过一个打开的文件。
我最终选择(或写)五个解决方案,一个天真的,一个欺骗的
和三个强大的。
>最简洁的naive solution,
使用内置数组函数。
> only possible solution based on tail command,有
一个大的问题:如果尾部不可用,它不运行,如
非Unix(Windows)或在不允许系统的受限环境中
功能。
>从文件搜索结束读取单个字节的解决方案
对于(和计数)新行字符,找到here。
>找到针对大文件优化的多字节缓冲解决方案
here。
> A略微为modified version of solution #4,其中缓冲区长度为
动态,根据要检索的行数决定。
所有解决方案工作。在它们返回预期结果的意义上
任何文件和任何数量的行,我们要求(除了解决方案#1,可以
在大文件的情况下打破PHP内存限制,不返回任何内容)。但是哪一个
更好?
性能测试
回答问题我运行测试。这是这些事情是怎么做的,不是吗?
我准备了一个示例100 KB文件,将不同的文件连接在一起
我的/ var / log目录。然后我写了一个PHP脚本,使用每一个
五个解来检索1,2,…,10,20,… 100,200,…,1000行
从文件的结尾。每个单独的测试重复十次(这是
例如5×28×10 = 1400次测试),测量平均流逝
时间(微秒)。
我在我的本地开发机器上运行脚本(Xubuntu 12.04,
PHP 5.3.10,2.70 GHz双核CPU,2 GB RAM)使用PHP命令行
解释器。这里是结果:
解决方案#1和#2似乎是更糟的。解决方案#3只有在我们需要的时候才是好的
读几行。解决方案#4和#5似乎是最好的。
注意动态缓冲区大小如何优化算法:执行时间有点小
较小的几行,因为减少的缓冲区。
让我们尝试一个更大的文件。如果我们必须读取10 MB日志文件怎么办?
现在解决方案#1是最糟糕的一个:事实上,加载整个10 MB文件
进入内存不是一个好主意。我运行测试也在1MB和100MB文件,
和它几乎相同的情况。
和小日志文件?这是10 KB文件的图形:
解决方案#1是现在最好的!将10 KB加载到内存中不是什么大问题
为PHP。 #4和#5也表现良好。但是这是一种边缘情况:10 KB日志
意味着像150/200行…
You can download all my test files, sources and results
07005.
最后的想法
Solution #5强烈推荐用于一般用例:工作伟大
与每个文件大小和执行特别好,当阅读几行。
避免solution #1如果你
应读取大于10 KB的文件。
解决方案#2
和#3不是我运行的每个测试的最好的:#2从不运行在小于2ms和#3受到的次数的严重影响线你问(工作相当不错,只有1或2行)。