關於php記憶體釋放問題(二)

2021-12-29 19:45:57 字數 1165 閱讀 5193

今天抽了一上午時間,來看了看之前解決過記憶體問題的**,相對來說,我對自己**的優化程式非常不滿意,一次性匯入四萬條資料就使**變得如此繁瑣,我想這不是根本的解決方法。通過網上檢索,對問題有進一步的分析:

在php記憶體溢位的問題中,前兩種方法就不提了(可以參考《關於php記憶體釋放問題》在博園中),不難分析出,其實問題的關鍵在於如何在迴圈中同步釋放記憶體,而不是迴圈幾百條來釋放一次,因為大家在除錯中會發現,如果我們把迴圈中復用性較高的**封裝到函式中,然後使用呼叫子函式的形式,會是程式的執行速度降低,大約幾十倍左右,這個下降幅度會隨著資料量的不同而改變。

迴圈巢狀的形式,在處理較大資料量的陣列,有很多使用 unset($a),的形式來及時釋放記憶體,但是 實際上這麼做是沒有意義的,引用以下分析:

」在引擎中,變數名和它們的值實際上是兩個不同的概念。值本身是乙個無名的zval*儲存體(在本例中,是乙個字串值),它被通過zend_hash_add()賦給變數$a。如果兩個變數名都指向同乙個值,會發生什麼呢?

此時,你可以實際地觀察$a或$b,並且會看到它們都包含字串"hello world"。遺憾的是,接下來,你繼續執行第三行**"unset($a);"。此時,unset()並不知道$a變數指向的資料還被另乙個變數所使用,因此它只是盲目地釋放掉該記憶體。任何隨後的對變數$b的訪問都將被分析為已經釋放的記憶體空間並因此導致引擎崩潰。

這個問題可以借助於zval(它有好幾種形式)的第四個成員refcount加以解決。當乙個變數被首次建立並賦值時,它的refcount被初始化為1,因為它被假定僅由最初建立它時相應的變數所使用。當你的**片斷開始把helloval賦給$b時,它需要把refcount的值增加為2;這樣以來,現在該值被兩個變數所引用:

現在,當unset()刪除原變數的$a相應的副本時,它就能夠從refcount引數中看到,還有另外其他人對該資料感興趣;因此,它應該只是減少refcount的計數值,然後不再管它。「

綜上,我們最需要做的其實是減少最初儲存資料的陣列,上面的例子,在迴圈中及時釋放掉陣列中已經處理完的元素,這樣隨著迴圈,記憶體佔用量的會一直上下波動(記憶體**機制問題),但不會一直增長,也就達到了我們最初的目的。當然,一次性最大的資料處理量還是取決於伺服器給php分配的記憶體,單次資料量讀入陣列就超出了限制,哪就是神仙也沒有辦法了,哈哈

UWSGI關於記憶體釋放問題

bin bash ps ef grep p project pid awk xargs kill 9 ulimit n 20000 usr local env project bin uwsgi s 127.0.0.1 7001 m r 200 p 4 evil reload on as 100 e...

關於資源保護與記憶體釋放問題

今天開始決定看看這方面的問題,現在罈子裡搜搜。在找找其它資料 1。tstrings 必須手工釋放 free tstringlist 在堆裡分配記憶體,沒有擁有者,所以沒有幫她釋放的類 2.關於form釋放問題 要徹底釋放窗體,光close是不夠的。一般需在onclose事件中寫action cafr...

vc記憶體釋放問題

在vc製作mfc之靜態dll時使用new分配記憶體後在使用delete時有時會報錯並且機率比較高,主要有下面的原因 一 記憶體已經被delete過,二 記憶體訪問越界,vc分配記憶體,除了分配你需要的記憶體空間外還會分配一些管理 單元,就在你分配空間的上界和下界,比如記憶體邊界標誌 0xfdfdfd...