關於php記憶體釋放問題
今天抽了一上午時間,來看了看之前解決過記憶體問題的代碼,相對來說,我對自己代碼的最佳化程式非常不滿意,一次性匯入四萬條資料就使代碼變得如此繁瑣,我想這不是根本的解決方案。通過網上檢索,對問題有進一步的分析: 在php記憶體溢出的問題中,前兩種方法就不提了(可以參考《關於php記憶體釋放問題》在博園中),不難分析出,其實問題的關鍵在於如何在迴圈中同步釋放記憶體,而不是迴圈幾百條來釋放一次,因為大家在調試中會發現,如果我們把迴圈中複用性較高的代碼封裝到函數中,然後使用調用子函數的形式,會是程式的執行速度降低,大約幾十倍左右,這個下降幅度會隨著資料量的不同而改變。 迴圈嵌套的形式,在處理較大資料量的數組,有很多使用 unset($a),的形式來及時釋放記憶體,但是 實際上這麼做是沒有意義的,引用以下分析: ”在引擎中,變數名和它們的值實際上是兩個不同的概念。值本身是一個無名的zval*儲存體(在本例中,是一個字串值),它被通過zend_hash_add()賦給變數$a。如果兩個變數名都指向同一個值,會發生什麼呢? { zval *helloval; MAKE_STD_ZVAL(helloval); ZVAL_STRING(helloval, "Hello World", 1); zend_hash_add(EG(active_symbol_table), "a", sizeof("a"),&helloval, sizeof(zval*), NULL); zend_hash_add(EG(active_symbol_table), "b", sizeof("b"),&helloval, sizeof(zval*), NULL);} 此時,你可以實際地觀察$a或$b,並且會看到它們都包含字串"Hello World"。遺憾的是,接下來,你繼續執行第三行代碼"unset($a);"。此時,unset()並不知道$a變數指向的資料還被另一個變數所使用,因此它只是盲目地釋放掉該記憶體。任何隨後的對變數$b的存取都將被分析為已經釋放的記憶體空間並因此導致引擎崩潰。 這個問題可以藉助於zval(它有好幾種形式)的第四個成員refcount加以解決。當一個變數被首次建立並賦值時,它的refcount被初始化為1,因為它被假定僅由最初建立它時相應的變數所使用。當你的代碼片斷開始把helloval賦給$b時,它需要把refcount的值增加為2;這樣以來,現在該值被兩個變數所引用: { zval *helloval; MAKE_STD_ZVAL(helloval); ZVAL_STRING(helloval, "Hello World", 1); zend_hash_add(EG(active_symbol_table), "a", sizeof("a"),&helloval, sizeof(zval*), NULL); ZVAL_ADDREF(helloval); zend_hash_add(EG(active_symbol_table), "b", sizeof("b"),&helloval,sizeof(zval*),NULL);} 現在,當unset()刪除原變數的$a相應的副本時,它就能夠從refcount參數中看到,還有另外其他人對該資料感興趣;因此,它應該只是減少refcount的計數值,然後不再管它。“ 綜上,我們最需要做的其實是減少最初儲存資料的數組,上面的例子,在迴圈中及時釋放掉數組中已經處理完的元素,這樣隨著迴圈,記憶體佔用量的會一直上下波動(記憶體回收機制問題),但不會一直增長,也就達到了我們最初的目的。當然,一次性最大的資料處理量還是取決於伺服器給php分配的記憶體,單次資料量讀入數組就超出了限制,哪就是神仙也沒有辦法了,哈哈。
http://www.bkjia.com/PHPjc/972220.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/972220.htmlTechArticle關於php記憶體釋放問題 今天抽了一上午時間,來看了看之前解決過記憶體問題的代碼,相對來說,我對自己代碼的最佳化程式非常不滿意,一次性...