作为PHP开发人员,我们并不常常需求担忧内存管理。PHP 引擎在我们背后做了很好的清算任务,短期执行上下文的 Web 效劳器模型意味着即使是最潦草的代码也不会形成耐久的影响。
很少状况下我们能够需求走出这个温馨的中央 —— 比如当我们试图在一个大型项目上运转 Composer 来创立我们可以创立的最小的 VPS 时,或许当我们需求在一个异样小的效劳器上读取大文件时。
前面的成绩就是我们将在本教程中深化讨论的。
在 GitHub 上可以找到本教程的源码。
权衡成功的标准
确保我们对代码停止任何改良的独一办法是测试一个不好的状况,然后将我们修复之后的测量与另一个停止比较。换句话说,除非我们知道“处置方案”对我们有多大的协助(假设有的话),否则我们不知道它能否真的是一个处置方案。
这里有两个我们可以关系的权衡标准。首先是CPU运用率。我们要处置的进程有多快或多慢?第二是内存运用状况。脚本执行时需求多少内存?这两个通常是成正比的 - 这意味着我们可以以CPU运用率为代价来降低内存运用,反之亦然。
在一个异步执行模型(如多进程或多线程的PHP运用顺序)中,CPU和内存的运用率是很重要的考量要素。在传统的PHP架构中,当任何一个值到达效劳器的极限时,这些通常都会成为成绩。
测量PHP内的CPU运用率是不实在践的。假设这是你要关注的范围,请思索在Ubuntu或MacOS上运用相似top的工具。关于Windows,请思索运用Linux子系统,以便在Ubuntu中运用top。
为了本教程的目的,我们将测量内存运用状况。我们将看看在“传统”的脚本中运用了多少内存。我们将执行一些优化策略并对其停止度量。最后,我希望你可以做出一个有阅历的选择。
我们查看内存运用多少的办法是:
// formatBytes is taken from the php.net documentation
memory_get_peak_usage();
function formatBytes($bytes, $precision = 2) {
$units = array("b", "kb", "mb", "gb", "tb");
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= (1 << (10 * $pow));
return round($bytes, $precision) . " " . $units[$pow];
}
我们将在脚本的最后运用这些函数,以便我们可以看到哪个脚本一次运用最大的内存。
我们的选择是什么?
这里有很多办法可以有效地读取文件。但是也有两种我们能够运用它们的状况。我们想要同时读取和处置一切数据,输入处置过的数据或依据我们所读取的内容执行其他操作。我们也能够想要转换一个数据流,而不需求真正拜访的数据。
让我们想象一下,关于第一种状况,我们希望读取一个文件,并且每10,000行创立一个独立排队的处置作业。我们需求在内存中保留至少10000行,并将它们传递给排队的任务管理器(无论采取何种方式)。
关于第二种状况,我们假定我们想要紧缩一个特别大的API照应的内容。我们不在乎它的内容是什么,但我们需求确保它是以紧缩方式备份的。
在这两种状况下,假设我们需求读取大文件,首先,我们需求知道数据是什么。第二,我们并不在乎数据是什么。让我们来探求这些选择吧...
逐行读取文件
有许多操作文件的函数,我们把部分结合到一个复杂的文件阅读器中(封装为一个办法):
// from memory.php
function formatBytes($bytes, $precision = 2) {
$units = array("b", "kb", "mb", "gb", "tb");
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= (1 << (10 * $pow));
(责任编辑:admin)