发布于 2026-01-06 10 阅读
0

由 For Loops 带来的缓慢死亡 DEV 的全球展示挑战赛,由 Mux 呈现:推介你的项目!

循环的缓慢死亡

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

本周我的任务是用 PHP 构建一个工作用的 Web 应用程序,该应用程序可以接收多个数据输入,将它们全部连接成一个多维关联数组,进行一些数学计算,然后将结果以 CSV 文件的形式输出给用户。

这些不同数据源中的数据,通常情况下,并非完美无缺。在将这些数据整合起来之前,需要先进行错误检查和清理。有些数据需要去除多余字符,有些数据需要筛选掉非数值,还有一些数据需要检查重复项。

数据清洗完毕后,需要将各个数据源相互比对,以便将记录连接起来。一个数据源包含一行数据的部分信息,另一个数据源包含更多信息,第三个数据源包含更多信息,最后,第四个数据源包含构成完整记录的最后一部分信息。

可以想象,这类应用涉及大量的迭代。遍历数据进行清理,遍历数据进行比较,在比较过程中再次迭代以检查是否存在进一步的相等性比较,并应用转换等等。

如今,空间廉价,但时间依然宝贵。这类迭代开发可能非常耗时。任何使用过 PHP 的人都知道,测试应用程序时遇到可怕的Fatal Error: Maximum execution time exceeded错误是什么感觉。

在真正遇到涉及时间复杂度的问题之前,大O符号的概念可能显得抽象。然而,只要花几分钟时间尝试优化代码以提高运行速度,你就能很快体会到它的重要性。

例如,请看以下内容:

for ($i = 0; $i < count($foo); $i++) {
    for ($x = 0; $x < $count($foo_two); $x++) {
       // do something...
    }
}

在比较两个数据数组时,这是一个非常常见的例子。你既要遍历其中一个数组,又要遍历另一个数组。这样做会造成什么成本呢?如果每个 for 循环的时间复杂度是 O(n),那么嵌套一个 for 循环的时间复杂度就是 O(n²)。这里n代表找到数据集末尾值所需的时间,因此每个 for 循环都会使操作的时间复杂度翻倍。这会迅速累积,并严重影响应用程序的性能。

当必须遍历数据时,你会怎么做?如何优化这种循环?

让我们来看一些技巧,特别是针对 PHP 的技巧,以提高我们的效率。

预设您的总额

我们都知道几乎所有编程语言中都有的经典 for 循环表达式:for ($i = 0; $i < count($array); $i++)` $iif (int '{i', '{j ...

$length = count($array);
for ($i = 0; $i < $length; $i++) {
    // do something
}

现在,由于我们的$length变量保存了数组的大小,因此我们的应用程序无需在每次循环时都检查数组长度。根据一项基准测试,使用预先计算好的变量而不是每次循环都强制计数,速度可以提升 94%。这可以迅速提升性能。

单引号与双引号

使用单引号和双引号的时间差异已经不像以前那么明显了。尽管如此,我仍然认为对于纯文本字符串使用单引号是一个好习惯。为什么呢?每次使用双引号时,PHP 都会检查引号内是否有需要执行的代码。因此,如果你要比较数组中的一个对象,并通过键引用其值,使用单引号$array['key']会告诉代码该对象key只是一个文本字符串,而使用$array["key"]双引号则会让它检查该对象是否key引用了除文本字符串之外的其他内容。

你在 for 循环里做什么?

每次循环时,你的程序都在做什么?仅仅遍历数据本身就需要时间。现在,再加上你对这些数据进行的任何操作的成本,你的应用程序的时间复杂度就会不断增加。有些操作比其他操作更耗时。当然,有时你别无选择,只能在 for 循环内执行耗时的操作,但如果可以避免,你的代码效率会更高。

字符串拼接就是一个常见的操作,它会迅速增加时间复杂度。这往往是程序中容易被忽视的部分。毕竟,你只是在把一些文本连接起来而已。但是,如果把每次拼接操作的次数乘以循环次数,它很容易就会降低程序的性能。

在 for 循环中直接拼接文本,有没有更高效的替代方案?不妨将文本添加到数组中,并在需要输出文本时再展开数组。将纯文本值添加到数组中可能比在遍历数据的过程中拼接文本更快。如果符合你的需求,另一种方法是直接输出echo文本而不进行拼接。当然,这并非总是可行,具体取决于你的应用程序需要实现的功能。

最终,将这些原则以及其他一些原则应用到我负责开发的应用程序上,显著提升了性能。在开发过程中将时间复杂度纳入考量,可以避免日后重构那些无法满足时间要求的现有代码时遇到的诸多麻烦。

大O符号不仅适用于白板面试,而且在实际工作中,对它的理解和运用可以编写出更高效的代码,从而让用户更满意,进而让开发者更满意。

文章来源:https://dev.to/benhayehudi/a-slow-death-by-for-loops-1004