• <sub id="h4knl"><ol id="h4knl"></ol></sub>
    <sup id="h4knl"></sup>
      <sub id="h4knl"></sub>

      <sub id="h4knl"><ol id="h4knl"><em id="h4knl"></em></ol></sub><s id="h4knl"></s>
      1. <strong id="h4knl"></strong>

      2. PHP對(duì)象相互引用的內(nèi)存溢出實(shí)例分析

        時(shí)間:2024-07-26 16:32:57 PHP 我要投稿
        • 相關(guān)推薦

        關(guān)于PHP對(duì)象相互引用的內(nèi)存溢出實(shí)例分析

          通常來(lái)說(shuō)使用腳本語(yǔ)言最大的好處之一就是可利用其擁有的自動(dòng)垃圾回收機(jī)制來(lái)釋放內(nèi)存。你不需要在使用完變量后做任何釋放內(nèi)存的處理,因?yàn)檫@些PHP會(huì)幫你完成。

          當(dāng)然,我們可以按自己的意愿調(diào)用 unset() 函數(shù)來(lái)釋放內(nèi)存,但通常不需要這么做。

          不過(guò)在PHP里,至少有一種情況內(nèi)存不會(huì)得到自動(dòng)釋放,即便是手動(dòng)調(diào)用 unset()。詳情可考PHP官網(wǎng)關(guān)于內(nèi)存泄露的分析:http://bugs.php.net/bug.php?id=33595。

          問(wèn)題癥狀如下:

          如果兩個(gè)對(duì)象之間存在著相互引用的關(guān)系,如“父對(duì)象-子對(duì)象”,對(duì)父對(duì)象調(diào)用 unset()不會(huì)釋放在子對(duì)象中引用父對(duì)象的內(nèi)存(即便父對(duì)象被垃圾回收,也不行)。

          是不是有些糊涂了?我們來(lái)看下面的這段代碼:

          bar = new Bar($this); }}class Bar { function __construct($foo = null){ $this->foo = $foo; }}while (true) { $foo = new Foo(); unset($foo); echo number_format(memory_get_usage()) . " ";}?>

          運(yùn)行這段代碼,你會(huì)看到內(nèi)存使用率越來(lái)越高越來(lái)越高,直到用光光。

          ...33,551,61633,551,97633,552,33633,552,696PHP Fatal error: Allowed memory size of 33554432 bytes exhausted(tried to allocate 16 bytes) in memleak.php on line 17

          對(duì)大部分PHP程序員來(lái)講這種情況不算是什么問(wèn)題。可如果你在一個(gè)長(zhǎng)期運(yùn)行的代碼中使用到了一大堆相互引用的對(duì)象,尤其是在對(duì)象相對(duì)較大的情況下,內(nèi)存會(huì)迅速地消耗殆盡。

          Userland解決方案

          雖然有些乏味、不優(yōu)雅,但之前提到的 bugs.php.net 鏈接中提供了一個(gè)解決方案。

          這個(gè)方案在釋放對(duì)象前使用一個(gè) destructor 方法以達(dá)到目的。Destructor 方法可將所有內(nèi)部的父對(duì)象引用全部清除,也就是說(shuō)可以將這部分本來(lái)會(huì)溢出的內(nèi)存釋放掉。

          以下是“修復(fù)后”的代碼:

          bar = new Bar($this); } function __destruct(){ unset($this->bar); }}class Bar { function __construct($foo = null){ $this->foo = $foo; }}while (true) { $foo = new Foo(); $foo->__destruct(); unset($foo); echo number_format(memory_get_usage()) . " ";}?>

          注意那個(gè)新增的Foo::__destruct()方法,以及在釋放對(duì)象前對(duì) $foo->__destruct() 的調(diào)用。現(xiàn)在這段代碼解決了內(nèi)存使用率一直增加的問(wèn)題,這么一來(lái),代碼就可以很好的工作了。

          PHP內(nèi)核解決方案

          為什么會(huì)有內(nèi)存溢出的發(fā)生?我對(duì)PHP內(nèi)核方面的研究并不精通,但可以確定的是此問(wèn)題與引用計(jì)數(shù)有關(guān)系。

          在 $bar 中引用 $foo 的引用計(jì)數(shù)不會(huì)因?yàn)楦笇?duì)象 $foo 被釋放而遞減,這時(shí)PHP認(rèn)為你仍需要 $foo 對(duì)象,也就不會(huì)釋放這部分的內(nèi)存。原理大致如此。

          通俗的來(lái)說(shuō),大體意思是:一個(gè)引用計(jì)數(shù)沒(méi)有遞減,所以一些內(nèi)存永遠(yuǎn)得不到釋放。

          此外在前面提到的 bugs.php.net 鏈接中指出了修改垃圾回收的過(guò)程將會(huì)犧牲極大的性能,需要讀者對(duì)此注意。

          與其改變垃圾回收的過(guò)程,為什么不用 unset() 對(duì)內(nèi)部對(duì)象做釋放的工作呢?(或者在釋放對(duì)象的時(shí)候調(diào)用 __destruct()?)

          也許PHP內(nèi)核開(kāi)發(fā)者可以在此或其他地方,對(duì)這種垃圾回收處理機(jī)制做出修改。

          

        《&.doc》
        将本文的Word文档下载到电脑,方便收藏和打印
        推荐度:
        点击下载文档

        【PHP對(duì)象相互引用的內(nèi)存溢出實(shí)例分析】相關(guān)文章:

        PHP對(duì)象注入的實(shí)例分析08-27

        Java內(nèi)存溢出的類(lèi)型10-03

        淺析php函數(shù)的實(shí)例06-08

        PHP中curl的使用實(shí)例07-31

        內(nèi)存故障分析09-01

        關(guān)于深入PHP內(nèi)存相關(guān)的功能特性詳解09-02

        PHP面向?qū)ο笾剌d重寫(xiě)的不同10-25

        德國(guó)留學(xué)申請(qǐng)實(shí)例分析09-28

        PHP中的排序函數(shù)區(qū)別分析08-23

        Javascript 閉包引起IE內(nèi)存泄露分析07-05

        在线咨询
        国产高潮无套免费视频_久久九九兔免费精品6_99精品热6080YY久久_国产91久久久久久无码
      3. <sub id="h4knl"><ol id="h4knl"></ol></sub>
        <sup id="h4knl"></sup>
          <sub id="h4knl"></sub>

          <sub id="h4knl"><ol id="h4knl"><em id="h4knl"></em></ol></sub><s id="h4knl"></s>
          1. <strong id="h4knl"></strong>

          2. 久久亚洲国产精品五月天婷 | 综合国产一区二区三区 | 在线观看91尤物 | 亚洲欧美午夜福利 | 亚洲男同gv片在线观看 | 午夜亚洲理论片在线观看 |

            關(guān)于PHP對(duì)象相互引用的內(nèi)存溢出實(shí)例分析

              通常來(lái)說(shuō)使用腳本語(yǔ)言最大的好處之一就是可利用其擁有的自動(dòng)垃圾回收機(jī)制來(lái)釋放內(nèi)存。你不需要在使用完變量后做任何釋放內(nèi)存的處理,因?yàn)檫@些PHP會(huì)幫你完成。

              當(dāng)然,我們可以按自己的意愿調(diào)用 unset() 函數(shù)來(lái)釋放內(nèi)存,但通常不需要這么做。

              不過(guò)在PHP里,至少有一種情況內(nèi)存不會(huì)得到自動(dòng)釋放,即便是手動(dòng)調(diào)用 unset()。詳情可考PHP官網(wǎng)關(guān)于內(nèi)存泄露的分析:http://bugs.php.net/bug.php?id=33595。

              問(wèn)題癥狀如下:

              如果兩個(gè)對(duì)象之間存在著相互引用的關(guān)系,如“父對(duì)象-子對(duì)象”,對(duì)父對(duì)象調(diào)用 unset()不會(huì)釋放在子對(duì)象中引用父對(duì)象的內(nèi)存(即便父對(duì)象被垃圾回收,也不行)。

              是不是有些糊涂了?我們來(lái)看下面的這段代碼:

              bar = new Bar($this); }}class Bar { function __construct($foo = null){ $this->foo = $foo; }}while (true) { $foo = new Foo(); unset($foo); echo number_format(memory_get_usage()) . " ";}?>

              運(yùn)行這段代碼,你會(huì)看到內(nèi)存使用率越來(lái)越高越來(lái)越高,直到用光光。

              ...33,551,61633,551,97633,552,33633,552,696PHP Fatal error: Allowed memory size of 33554432 bytes exhausted(tried to allocate 16 bytes) in memleak.php on line 17

              對(duì)大部分PHP程序員來(lái)講這種情況不算是什么問(wèn)題。可如果你在一個(gè)長(zhǎng)期運(yùn)行的代碼中使用到了一大堆相互引用的對(duì)象,尤其是在對(duì)象相對(duì)較大的情況下,內(nèi)存會(huì)迅速地消耗殆盡。

              Userland解決方案

              雖然有些乏味、不優(yōu)雅,但之前提到的 bugs.php.net 鏈接中提供了一個(gè)解決方案。

              這個(gè)方案在釋放對(duì)象前使用一個(gè) destructor 方法以達(dá)到目的。Destructor 方法可將所有內(nèi)部的父對(duì)象引用全部清除,也就是說(shuō)可以將這部分本來(lái)會(huì)溢出的內(nèi)存釋放掉。

              以下是“修復(fù)后”的代碼:

              bar = new Bar($this); } function __destruct(){ unset($this->bar); }}class Bar { function __construct($foo = null){ $this->foo = $foo; }}while (true) { $foo = new Foo(); $foo->__destruct(); unset($foo); echo number_format(memory_get_usage()) . " ";}?>

              注意那個(gè)新增的Foo::__destruct()方法,以及在釋放對(duì)象前對(duì) $foo->__destruct() 的調(diào)用。現(xiàn)在這段代碼解決了內(nèi)存使用率一直增加的問(wèn)題,這么一來(lái),代碼就可以很好的工作了。

              PHP內(nèi)核解決方案

              為什么會(huì)有內(nèi)存溢出的發(fā)生?我對(duì)PHP內(nèi)核方面的研究并不精通,但可以確定的是此問(wèn)題與引用計(jì)數(shù)有關(guān)系。

              在 $bar 中引用 $foo 的引用計(jì)數(shù)不會(huì)因?yàn)楦笇?duì)象 $foo 被釋放而遞減,這時(shí)PHP認(rèn)為你仍需要 $foo 對(duì)象,也就不會(huì)釋放這部分的內(nèi)存。原理大致如此。

              通俗的來(lái)說(shuō),大體意思是:一個(gè)引用計(jì)數(shù)沒(méi)有遞減,所以一些內(nèi)存永遠(yuǎn)得不到釋放。

              此外在前面提到的 bugs.php.net 鏈接中指出了修改垃圾回收的過(guò)程將會(huì)犧牲極大的性能,需要讀者對(duì)此注意。

              與其改變垃圾回收的過(guò)程,為什么不用 unset() 對(duì)內(nèi)部對(duì)象做釋放的工作呢?(或者在釋放對(duì)象的時(shí)候調(diào)用 __destruct()?)

              也許PHP內(nèi)核開(kāi)發(fā)者可以在此或其他地方,對(duì)這種垃圾回收處理機(jī)制做出修改。