ホームページ >バックエンド開発 >PHPの問題 >小さな変更で json_decode メモリの 70% を節約できるでしょうか?

小さな変更で json_decode メモリの 70% を節約できるでしょうか?

醉折花枝作酒筹
醉折花枝作酒筹転載
2021-07-22 17:41:491915ブラウズ

json_decode は、JSON 形式の文字列をデコードし、JSON 形式の文字列を受け入れて、それを PHP 変数に変換します。しかし、json_decode を実行するとメモリを超過する可能性があります。

小さな変更で json_decode メモリの 70% を節約できるでしょうか?

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 の解析:

Save MAC address メソッドArray MethodString メソッドJSON ファイル サイズ9.6M8.6M (各要素は、引用符) #平均メモリ使用量 平均 json_decode 解析時間100 万 MAC の解析:
72.4M 8.7M
0.73s 0.41s

MAC アドレス保存方式 #Array 方式 #JSON ファイルサイズ 20M18M平均メモリ使用量204.6M54.2M平均json_decode 解析時間 #1.61s0.81s##200 万 MAC の解析:
#String 方式
MAC アドレス保存メソッド

配列メソッド文字列メソッド 40M36M108.2M#3.05s1.53sphp ビデオ チュートリアル
JSON ファイル サイズ
平均メモリ使用量 409.0M
平均 json_decode 解析時間
推奨学習:

以上が小さな変更で json_decode メモリの 70% を節約できるでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。