1

我正在重写一些脚本以将机器生成的日志从 perl 解析为 php 文件范围从 20mb~400mb 我遇到了这个问题来决定我应该使用 file() 还是 fopen()+fgets() 组合去通过文件以获得更快的性能。

这是基本的运行,我在打开它之前检查文件大小,如果文件大于 100mb(非常罕见的情况,但它确实会不时发生)我会走 fopen+fgets 路线,因为我只是碰到了脚本的内存限制为 384mb,任何大于 100mb 的文件都有可能导致致命错误。否则,我使用 file()。

我只在两种方法中从头到尾逐行浏览文件一次。

这是一个问题,是否值得保留代码的 file() 部分来处理小文件?我不知道 file() (我也使用 SKIP_EMPTY_LINE 选项)在 php 中是如何工作的,它是直接将文件映射到内存中,还是在遍历时将文件逐行推入内存?我对其进行了一些基准测试,性能非常接近,40mb 文件的平均差异约为 0.1 秒,并且 file() 在大约 80% 的时间(在同一文件集的 200 次测试中)比 fopen+fgets 具有优势。

删除文件部分肯定可以为我节省一些系统内存,并且考虑到我同时运行相同脚本的 3 个实例,它可以在同时托管数据库和其他的 12G 系统上为我节省 1G 的内存废话。但我也不想让脚本的性能下降,因为每天大约有 10k 的这些日志进入,实际上 0.1 秒的差异加起来。

任何建议都会对 TIA 有所帮助!

4

1 回答 1

2

我建议坚持使用一种机制,例如foreach(new \SplFileObject('file.log') as $line). 拆分您的输入文件并并行处理它们,每个 CPU 内核 2-3x。奖励:低于同一系统上的数据库的优先级。在 PHP 中,这意味着一次生成 N 个脚本副本,其中每个副本都有自己的文件列表或目录。由于您在谈论重写并且 IO 性能是一个问题,因此请在此处考虑具有更多功能的其他平台,例如 Java 7 NIO、nodejs 异步 IO、C# TPL。

于 2012-05-05T03:28:56.983 回答