站長資訊網
        最全最豐富的資訊網站

        定位分析內存泄漏的原因和后果

        定位分析內存泄漏的原因和后果

        內部泄漏錯誤代碼:

        Fatal error: Allowed memory size of X bytes exhausted (tried to allocate Y bytes)

        觀察php程序內存使用情況

        php提提供了兩個方法來獲取當前程序的內存使用情況。
        memorygetusage(),這個函數的作用是獲取目前PHP腳本所用的內存大小。

        memorygetpeak_usage(),這個函數的作用返回當前腳本到目前位置所占用的內存峰值,這樣就可能獲取到目前的腳本的內存需求情況。

        int memory_get_usage ([ bool $real_usage = false ] )   int memory_get_peak_usage ([ bool $real_usage = false ] )

        函數默認得到的是調用emalloc()占用的內存,如果設置參數為TRUE,則得到的是實際程序向系統申請的內存。因為 PHP 有自己的內存管理機制,所以有時候盡管內部已經釋放了內存但并沒有還給系統。

        linux 系統文件 /proc/{$pid}/status 會記錄某個進程的運行狀態,里面的 VmRSS 字段記錄了該進程使用的常駐物理內存(Residence),這個就是該進程實際占用的物理內存了,用這個數據比較靠譜,在程序里面提取這個值也很容易 。

        場景一:程序操作數據過大

        情景還原:一次性讀取超過php可用內存上限的數據導致內存耗盡

        實例:

        <?php  ini_set('memory_limit', '128M');   $string = str_pad('1', 128 * 1024 * 1024);     Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 134217729 bytes)  in /Users/zouyi/php-oom/bigfile.php on line 3

        這是告訴我們程序運行時試圖分配新內存時由于達到了PHP允許分配的內存上限而拋出致命錯誤,無法繼續執行了,在 java 開發中一般稱之為 OOM ( Out Of Memory ) 。
        PHP 配置內存上限是在php.ini中設置memory_limit,PHP 5.2 以前這個默認值是8M,PHP 5.2 的默認值是16M,在這之后的版本默認值都是128M。
        問題現象:特定數據處理時可復現,做任何 IO 操作都有可能遇到此類問題,比如:一次 mysql 查詢返回大量數據、一次把大文件讀取進程序等。

        解決方法:

        1、能用錢解決的問題都不是問題,如果程序要讀大文件的機會不是很多,且上限可預期,那么通過ini_set('memory_limit', '1G');來設置一個更大的值或者memory_limit=-1。內存管夠的話讓程序一直跑也可以。

        2、如果程序需要考慮在小內存機器上也能正常使用,那就需要優化程序了。如下,代碼復雜了很多。

        <?php   //php7 以下版本通過 composer 引入 paragonie/random_compat ,為了方便來生成一個隨機名稱的臨時文件   require "vendor/autoload.php";     ini_set('memory_limit', '128M');   //生成臨時文件存放大字符串   $fileName = 'tmp'.bin2hex(random_bytes(5)).'.txt';   touch($fileName);   for ( $i = 0; $i < 128; $i++ ) {       $string = str_pad('1', 1 * 1024 * 1024);       file_put_contents($fileName, $string, FILE_APPEND);   }   $handle = fopen($fileName, "r");   for ( $i = 0; $i <= filesize($fileName) / 1 * 1024 * 1024; $i++ )  {      //do something      $string = fread($handle, 1 * 1024 * 1024);   }     fclose($handle);   unlink($fileName);

        場景二、程序操作大數據時產生拷貝

        情景還原:執行過程中對大變量進行了復制,導致內存不夠用。

        <?php   ini_set("memory_limit",'1M');     $string = str_pad('1', 1* 750 *1024);   $string2 = $string;  $string2 .= '1';     Fatal error: Allowed memory size of 1048576 bytes exhausted (tried to allocate 768001 bytes)  in /Users/zouyi/php-oom/unset.php on line 8     Call Stack:       0.0004     235440   1. {main}() /Users/zouyi/php-oom/unset.php:0    zend_mm_heap corrupted

        問題現象:局部代碼執行過程中占用內存翻倍。

        問題分析:
        php 是寫時復制(Copy On Write),也就是說,當新變量被賦值時內存不發生變化,直到新變量的內容被操作時才會產生復制。

        解決方法:

        及早釋放無用變量,或者以引用的形式操作原始數據。

        <?php   ini_set("memory_limit",'1M');     $string = str_pad('1', 1* 750 *1024);   $string2 = $string;  unset($string);   $string2 .= '1';     <?php   ini_set("memory_limit",'1M');     $string = str_pad('1', 1* 750 *1024);   $string2 = &$string;   $string2 .= '1';     unset($string2, $string);

        場景三、配置不合理系統資源耗盡

        情景還原:因配置不合理導致內存不夠用,2G 內存機器上設置最大可以啟動 100 個 php-fpm 子進程,但實際啟動了 50 個 php-fpm 子進程后無法再啟動

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 日本VA欧美VA精品发布| 97精品伊人久久大香线蕉app| 日本VA欧美VA精品发布| 国产成人精品久久综合| 久久精品国产亚洲精品2020 | 538国产精品一区二区在线| 人妻少妇看A偷人无码精品视频| 亚洲精品私拍国产福利在线| 国产精品无码午夜福利| 亚洲Av无码精品色午夜| 免费看一级毛片在线观看精品视频 | 99久久精品国产一区二区三区| 经典国产乱子伦精品视频| 无码人妻一区二区三区精品视频| 99热精品毛片全部国产无缓冲| 国产成人精品视频在放| 久久久久久亚洲Av无码精品专口| 亚洲精品黄色视频在线观看免费资源| 好湿好大硬得深一点动态图91精品福利一区二区 | 欧美精品福利在线视频| 国产精品 91 第一页| 最新国产精品亚洲| 久久精品国产99国产精品澳门| 99久久成人国产精品免费| 国产乱子伦精品无码码专区| 久久久免费精品re6| 日韩精品专区在线影院重磅| 一本一道久久a久久精品综合 | 国产精品视频九九九| 国产精品福利区一区二区三区四区| 久久精品国产精品青草app| 久久精品国产免费| 亚洲国产精品免费视频| 91精品国产麻豆国产自产在线| 日韩精品在线看| 四虎精品成人免费观看| 久久福利青草精品资源站| 国产欧美国产精品第一区| 热re99久久精品国产99热| 白浆都出来了视频国产精品 | 国产成人精品一区二三区在线观看|