json_decode對JSON格式的字串進行解碼,接受一個JSON格式的字串並且把它轉換為PHP變數。但是運行json_decode可能會出現超出記憶體上線,這是該怎麼辦?
如果你用PHP的json_decode函數解析JSON字串,而且JSON字串中包含一個大量元素的數組,那你就要小心解析過程中PHP超出記憶體上限了。
筆者在開發時遇到一個JSON檔案需要解析,該JSON中包含了一個由眾多MAC位址組成的數組,像這樣:
{ "name": "MAC File", "date": "2017-11-08", "macList": [ "11-11-11-11-11-11", "22-22-22-22-22-22", ... ] }
結果json_decode過程中超出了PHP默認的128M內存上限。
WHAT,超限了? !這張JSON檔才 10M 啊!
在大罵「這函數是不是有BUG」之後,仔細推敲下,發現問題出在MAC位址構成的陣列上。要知道PHP的陣列是很吃記憶體的。
PHP數組究竟多吃內存,可以做個簡單的試驗,向數組內放入50萬個MAC地址,打印內存佔用量:
$a = []; for ($i = 0; $i !== 500000; $i++) { $a[] = '11-11-11-11-11-11'; } echo memory_get_usage() . PHP_EOL;
如果把這些MAC地址寫在一個文件裡,理論上只佔9.6M 磁碟空間,但是PHP數組維護相同的訊息,卻佔了72.4M 記憶體。
有辦法解決json_deocde時的記憶體超限嗎?當然,簡單粗暴點的話就把記憶體上限調高:
ini_set('memory_limit','1024M');
雖然可行,但會引發一個問題,就是:
可能被其他語言的工程師嘲笑PHP佔內存。
那有沒有更明智的辦法解決記憶體超限問題?
有。因為PHP數組佔用記憶體很大,所以我們要避免json_decode在解碼時產生巨大數組。怎麼做呢?這就要從JSON的編碼格式下手,例如可以把巨大的JSON數組修改成字串:
{ "name": "MAC File", "date": "2017-11-08", "macList": "11-11-11-11-11-11,22-22-22-22-22-22,...", }
我把macList從數組轉換成以逗號分割的字串。這樣可以避免json_decde產生一個巨大無比的數組,取而代之的是一個超長的字串。
字串佔用的記憶體量可比陣列小多了,剛才50萬個MAC位址,瞬間只佔9.7M的記憶體。修改完之後,json_decode順利解析成功,而且解析速度更快了。
原先macList是個數組,可以透過foreach遍歷其中的元素,現在是字串了,該怎麼遍歷呢?
不難,可以用strtok:
$tok = strtok($macList, ','); while ($tok !== false) { $mac = $tok; $tok = strtok(','); }
遍歷的難度沒有增加多少,對吧?
你可能會問,這種方法可以對付簡單的JSON數組,如果一個JSON數組的每個元素是個JSON對象,該怎麼辦?
我們可以這樣建構字串:
{ "list": '{"name":"obj1"}###{"name":"obj2"}###...' }
字串由一個小的JSON組成,它們之間用特殊的標記
分割。在解析時,根據特殊標記切分出一個個JSON對象,再用json_decode逐個解析:$tok = strtok($objectList, '###'); // 按###切割 while ($tok !== false) { $objectStr = $tok; // 每切割出一个JSON对象就解码 $object = json_decode($objectStr, true); $tok = strtok('###'); }你也可以自創一種編碼/解析這個超長字串的方法,總之最終目標就是避免json_decode在解碼過程中產生超大數組。 透過本文,你應該略到了PHP Array吃記憶體的能力。把JSON中的陣列替換成字串表示,可以節省大量的記憶體。我還跑了一個比較數據,給大家參考:解析50萬個MAC:
保存MAC位址方式 | 數組方式 | 字串方式 |
---|---|---|
JSON檔案大小 | 9.6M | 8.6M(每個元素省了一對引號) |
平均記憶體佔用 | 72.4M | #8.7M |
平均json_decode解析時間 | 0.73s | 0.41s |
#儲存MAC位址方式 | 陣列方式 | 字串方式 |
---|---|---|
JSON檔案大小 | 20M | 18M |
平均記憶體佔用 | 204.6M | #54.2M |
#平均json_decode解析時間 | ##1.61s | 0.81s |
解析200萬個MAC:
儲存MAC位址方式 | 陣列方式 | 字串方式 |
---|---|---|
JSON檔案大小 | 40M | 36M |
#平均記憶體佔用 | 409.0M | 108.2M |
平均json_decode解析時間 | 3.05s | 1.53s |
以上是小小一個改動,竟能讓json_decode記憶體節省70%?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器