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 です。
え、限界を超えていますか? !この JSON ファイルはわずか 10M です。
「この機能にバグがあるのでは?」と罵った後、よく考えてみると、問題は MAC アドレスの配列にあることがわかりました。 PHP 配列は大量のメモリを消費することを知っておく必要があります。
PHP 配列はどのくらいのメモリを使用しますか? 500,000 個の MAC アドレスを配列に入力し、メモリ使用量を出力することで、簡単な実験を行うことができます:
$a = []; for ($i = 0; $i !== 500000; $i++) { $a[] = '11-11-11-11-11-11'; } echo memory_get_usage() . PHP_EOL;
これらの MAC アドレスを A ファイルに書き込むと、理論的には 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 が巨大な配列を生成することがなくなり、非常に長い文字列に置き換えられます。
文字列が占有するメモリの量は、配列のメモリの量よりもはるかに少なく、先ほどの 500,000 個の 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 を使用して 1 つずつ解析されます:$tok = strtok($objectList, '###'); // 按###切割 while ($tok !== false) { $objectStr = $tok; // 每切割出一个JSON对象就解码 $object = json_decode($objectStr, true); $tok = strtok('###'); }この非常に長い文字列をエンコード/解析する独自の方法を作成することもできます。デコード処理中に json_decode が非常に大きな配列を生成するのを避けてください。 この記事を通じて、PHP 配列がメモリを消費する能力を垣間見ることができるはずです。 JSON 内の配列を文字列表現に置き換えると、大量のメモリを節約できます。参考のために比較データも実行しました: 500,000 MAC の解析:
Array Method | String メソッド | |
---|---|---|
9.6M | 8.6M (各要素は、引用符) | |
72.4M | 8.7M | |
0.73s | 0.41s |
#String 方式 | #JSON ファイルサイズ | |
---|---|---|
平均メモリ使用量 | 204.6M | |
平均json_decode 解析時間 | #1.61s | |
##200 万 MAC の解析: |
JSON ファイル サイズ | ||
---|---|---|
平均メモリ使用量 | 409.0M | |
平均 json_decode 解析時間 | #3.05s1.53s | |
推奨学習: | php ビデオ チュートリアル
以上が小さな変更で json_decode メモリの 70% を節約できるでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。