【问题标题】:When unset() should really be used?什么时候应该真正使用 unset()?
【发布时间】:2013-05-09 13:30:20
【问题描述】:

我对使用unset() 语言结构感到好奇,我几乎在所有地方都使用了内存或声明了一些变量(无论结构如何)。

我的意思是,当有人声明变量时,它应该什么时候真正留给GC,或者是unset()


示例 1:

<?php
$buffer = array(/* over 1000 elements  */);

// 1) some long code, that uses $buffer

// 2) some long code, that does not use $buffer
?>
  1. $buffer 是否有可能影响第 2 点的性能?
  2. 在进入第 2 点之前,我真的需要(或应该)做unset($buffer) 吗?

示例 2:

<?php
function someFunc(/* some args */){
    $buffer = new VeryLargeObject();

    // 1) some actions with $buffer methods and properties

    // 2) some actions without usage of $buffer

    return $something;
}
?>
  1. 在进入第 2 点之前,我真的需要(或应该)在 someFunc()s 的正文中执行 unset($buffer) 吗?
  2. 当函数结束或找到return 语句时,GC 会在someFunc()s 范围内释放所有分配的内存(包括引用和对象)吗?

我对技术解释很感兴趣,但也欢迎代码风格的建议。

谢谢。

【问题讨论】:

  • 完成后取消设置任何变量并没有错,但是对于像这样的大对象,我肯定会说。我确信在第 2 部分中运行的代码会享受额外的空间。
  • @Orangepill 我也这么认为,但一些程序员(在我的工作岗位上)认为,没有必要这样做,因为“PHP 有 GC !!”。例如,很多 Symfony 核心对象都是 LARGE,但它们存在于方法中。它们是否应该在完成后取消设置,而不是等待函数结束?此外,他们提到“php_memory_limit 足够大”以忽略 unset(),无论如何 PHP 都会这样做。
  • unset 将释放内存 only when the object (not variable) is no longer referenced。 GC 将very slightly decrease performance。但总的来说,取消设置不再使用的变量并没有错。
  • @Passerby 谢谢,我会在进一步的编码中考虑它。

标签: php performance memory-management garbage-collection unset


【解决方案1】:

在php中,脚本执行完后所有的内存都会被清理干净,而且大部分时间已经足够了。

来自 php.net:

unset() 就像它的名字所说的那样 - 取消设置一个变量。它不是 强制立即释放内存。 PHP 的垃圾收集器会这样做 当它认为合适时 - 有意尽快,因为那些 CPU 周期不是 无论如何都需要,或者直到脚本用完之前 记忆,无论先发生什么。

如果你正在做 $whatever = null;那么你正在重写变量的 数据。您可能会更快地释放/缩小内存,但它可能会窃取 CPU 从真正需要它们的代码中循环,从而导致 更长的整体执行时间。

实际上,您很少会使用unset() 来清理内存,这篇文章对此进行了很好的描述: https://stackoverflow.com/a/2617786/1870446

通过对变量执行unset(),您将变量标记为“垃圾收集”,因此内存不会立即可用。变量不再有数据,但堆栈保持较大的大小。
在 PHP >= 5.3.0 中,您可以调用 gc_collect_cycles() 来强制通过 GC。 (先做gc_enable()之后)。
但是您必须了解 PHP 是脚本语言,它不是 Java,因此您不应该将其视为一种语言。如果您的脚本真的需要大量的 RAM - 您可以使用 unset 并且当脚本接近超过内存时 - GC 将触发并清理所有无用的内容,包括您未设置的变量。但在大多数情况下,您可以忘记它。
此外,如果您想取消设置您不使用的每个变量 - 不要。它实际上会使您的脚本执行时间更长 - 通过使用更多 CPU 周期 - 以获得在大多数情况下永远不需要的空闲内存。
有些人还说他们使用unset 来明确表明他们不会再使用变量了。我也觉得这是一种不好的做法,对我来说,它只是让所有这些无用的未设置的代码更加冗长。

【讨论】:

  • 你的意思是,unset() 根本不会触发GC
  • 刚刚阅读更新的答案。清楚,但我需要更多意见。目前,我会接受它,如果在不久的将来不会提供其他足够的答案。谢谢。
猜你喜欢
  • 1970-01-01
  • 2023-04-02
  • 2011-04-15
  • 2017-04-10
  • 2012-03-19
  • 2018-05-12
  • 2018-12-11
  • 1970-01-01
  • 2022-09-28
相关资源
最近更新 更多