php程式記憶體優化之陣列操作優化

2022-08-23 10:45:12 字數 2696 閱讀 1053

一、前言out of memory (allocated 364904448) (tried to allocate 262144 bytes)

也就是傳統的記憶體不足報錯,問題是我本地設定的記憶體已經是1280m了,簡直不能忍。因此這裡一步步的看一篇**,記錄一下需要優化的地方,主要是針對陣列的

二、優化前準備

1、首先是檢視php的當前記憶體設定

windows: 開啟php.ini,搜尋:memory_limit ,一般設定為128m夠用

linux: 執行「php -i | grep loaded configuration file」來找到對應的配置檔案。

注: 這個命令是搜尋php程式的配置檔案所在位置,開啟phpinfo,可以看到有個loaded configuration file 選項,對應

的就是php.ini檔案的位置

2、乙個php陣列能占用多大記憶體

參考:通過大佬的分析,我們可以知道:

(1)php對於陣列的利用效率很低,乙個在c語言裡面100m 記憶體的陣列,在php裡面就要1g;

(2)php空陣列都要14(zval) + 39(hashtable) + 33(arbuckets) = 86 個位元組

(3)php檢視記憶體方法:memory_get_usage() ,具體用法: echo memory_get_usage(); 即可,博主通過該方法,確認記憶體瓶頸出在了陣列部分

三、優化過程

1、**冗餘

$arr = ;

foreach($response['hits']['hits'] as $v)

unset($v);

//加上原來沒有的一些字段,篩選掉沒有pixel的資料

foreach($arr as $key=>$v)

}優化點評: 這裡的$arr是完全不必要的,既然下面還是要篩選,那麼直接迴圈下面的那個$response['hits']['hits']即可,如果$arr是很大的陣列,那麼在賦值之後,又要開闢一塊記憶體給它。所以要盡量避免這種情況的發生。

2、陣列賦值給另乙個空陣列

if(count($this->arresindex) > 0)else

優化點評: 像這種陣列賦值操作盡量少做。因為把 $arr賦值給$this->arresindex之後,如果$this->arresindex的值改變了,那麼使用的記憶體相當於翻倍的效果。其次是賦值之後,這個$arr其實已經沒用了,但是由於咱們沒有進行unset,所以就造成這個$arr還在占用記憶體的情況。建議是unset($arr),也就是unset掉咱們不用的那些陣列。

正常的賦值是不會發生記憶體改變的,但是當賦值的新陣列發生改動的時候,php就會新開闢記憶體給新的陣列,這裡會造成無謂的記憶體消耗。最好是不要直接這樣賦值,如果非賦值不可的話,記得加上『&』符號,通過傳引用直接傳遞位址給新陣列,這樣當新陣列發生變化的時候,更改的還是原來的那塊記憶體。

3、把陣列傳參給函式

$this->getscrolldata($repos);

優化點評: 這裡的$repos是乙個陣列。正常來說,傳值傳陣列也是可以的,但是如果這個陣列裡面的元素是萬級別的,那麼

這個操作也是非常耗記憶體的。在php程式中,只要傳參,引數都會拷貝乙份,所以值越大,耗的記憶體越大。針對這種情況,

建議是在類裡面定義全域性變數,然後函式體裡面通過:$this->repos來操作這個陣列。也可以考慮使用傳引用的方式,因為使用&的話,傳遞過去的事乙個記憶體位址,位數並不大。

4、把判斷條件寫在迴圈外面,避免每次都要迴圈的情況

foreach($this->arresindex as $k=>&$v)

}優化點評: 這個操作也有問題,如果if條件滿足的話還好。如果if條件不滿足的話,在業務層面根本就不需要進行這部分操作。但是由於咱們的forteach迴圈在最外面,所以照樣會迴圈一下陣列。問題這是個很大的陣列,消耗的記憶體也很可觀。

5、unset掉比較大的變數

針對一些比較大的變數(最好大於256位元組),如果只是臨時使用的話,使用完之後記得unset()掉。如果對變數進行'&'傳引用的話,會增加該記憶體的引用計數,直接unset()變數並不會立馬釋放變數,因為unset只是斷開乙個變數到一塊記憶體區域的連線,同時將該記憶體區域的引用計數-1,如果把引用賦值的那個變數也unset()掉才會立馬釋放記憶體。

6、單個大陣列消耗太多記憶體的解決方案

參考:通過存入字串的方式優化,使用陣列的時候就再把字串轉化為陣列

7、迴圈操作db

這個問題是老生常談了,博主**裡沒有出現這個情況,不過大家還是注意下比較好。迴圈不斷操作db,非常影響程式效能。

四、總結

以上的優化部分也是博主一步步看著**慢慢優化的,相對而言都是一些比較淺層面的優化。不過這些問題也告訴我們,寫完**記得要再看一遍,如果可以的話,在開始編寫**的時候就要注意效能問題。最差勁也要實現業務之後,重新看一遍**,優化**結構,釋放掉不必要的變數,改掉太消耗記憶體的操作。

博主這裡優化之後,原來的**1280m的記憶體都不夠用,現在128m的記憶體妥妥的。程式執行下來,總共占用記憶體10m左右,還是比較合適的。如果大家也出現記憶體不足的情況,那麼除了增大本身的php記憶體之外,也要考慮優化下程式哦。

《C 應用程式效能優化》之程式記憶體

乙個程式占用的記憶體區通常分5種,如下 全域性 靜態資料區 儲存全域性變數和靜態變數 常量資料區 儲存程式中的常量 字串等,不可修改 區 儲存 資料 棧 儲存自動變數 區域性變數,傳遞引數 堆 使用者控制的儲存區,儲存動態產生的資料 程式在分配記憶體時為了加快訪問速度,採取的一種分配策略。每個特定平...

效能優化之MySQL優化(四) 作業系統配置優化

資料庫是基於作業系統的,目前大多數的mysql都是安裝在linux系統之上,所以對於作業系統的一些引數配置也影響到mysql的效能,下面就列出一些常用到 的系統配置。網路方面的配置,要修改 etc sysctl.conf檔案 增加tcp支援的佇列書 net.ipv4.tcp max syn back...

JAVA優化程式設計 記憶體管理之 (4)陣列的建立

4 陣列的建立 陣列空間的申請分為顯式申請與隱式申請兩種。顯式申請是指在程式中直接給出陣列的型別與長度,例如 int intarray newint 1024 上面的這行 就是顯式地向系統一次性申請了大小為1kb的整數型別的記憶體空間,這樣的宣告方式一般出現在對檔案或網路的資源讀取的處理 中,往往用...