Maison  >  Article  >  développement back-end  >  Un petit changement peut économiser 70 % de la mémoire json_decode ?

Un petit changement peut économiser 70 % de la mémoire json_decode ?

醉折花枝作酒筹
醉折花枝作酒筹avant
2021-07-22 17:41:491755parcourir

json_decode décode une chaîne au format JSON, accepte une chaîne au format JSON et la convertit en variable PHP. Mais lors de l'exécution de json_decode, la mémoire peut être dépassée. Que dois-je faire ?

Un petit changement peut économiser 70 % de la mémoire json_decode ?

Si vous utilisez la fonction json_decode de PHP pour analyser une chaîne JSON et que la chaîne JSON contient un tableau avec un grand nombre d'éléments, vous devez alors faire attention à ce que PHP dépasse la limite de mémoire pendant le processus d'analyse.

L'auteur a rencontré un fichier JSON qui devait être analysé pendant le développement. Le JSON contenait un tableau composé de nombreuses adresses MAC, comme ceci :

{
    "name": "MAC File",
    "date": "2017-11-08",
    "macList": [
        "11-11-11-11-11-11",
        "22-22-22-22-22-22",
        ...
    ]
}

En conséquence, le processus json_decode a dépassé la limite de mémoire par défaut de PHP de 128 Mo.

QUOI, est-ce que c'est au-delà de la limite ? ! Ce fichier JSON ne fait que 10 Mo !

Après avoir maudit "Y a-t-il un bug dans cette fonction ?", après mûre réflexion, j'ai découvert que le problème réside dans le tableau composé d'adresses MAC. Il faut savoir que les tableaux PHP consomment beaucoup de mémoire.

Combien de mémoire le tableau PHP utilise-t-il ? Vous pouvez faire une expérience simple. Mettez 500 000 adresses MAC dans le tableau et imprimez l'utilisation de la mémoire :

$a = [];
for ($i = 0; $i !== 500000; $i++) {
    $a[] = '11-11-11-11-11-11';
}
echo memory_get_usage() . PHP_EOL;

Si vous écrivez ces adresses MAC dans un fichier, théoriquement seulement 9,6 M d'espace disque, mais le tableau PHP conserve les mêmes informations, mais occupe 72,4 Mo de mémoire.

Existe-t-il un moyen de résoudre le débordement de mémoire lorsque json_deocde ? Bien sûr, pour être simple et brut, augmentez simplement la limite de mémoire :

ini_set('memory_limit','1024M');

Bien que cela soit faisable, cela posera un problème, qui est :

peut être ridiculisé par les ingénieurs d'autres langages pour l'empreinte mémoire de PHP.

Existe-t-il un moyen plus intelligent de résoudre le problème de dépassement de limite de mémoire ?

Oui. Étant donné que les tableaux PHP occupent beaucoup de mémoire, nous devons éviter que json_decode génère d'énormes tableaux lors du décodage. Comment faire ? Cela commence par le format d'encodage JSON. Par exemple, vous pouvez modifier un énorme tableau JSON en chaîne :

{
    "name": "MAC File",
    "date": "2017-11-08",
    "macList": "11-11-11-11-11-11,22-22-22-22-22-22,...",
}

J'ai converti macList d'un tableau en une chaîne séparée par des virgules. Cela empêche json_decde de générer un énorme tableau et le remplace par une chaîne extrêmement longue.

La quantité de mémoire occupée par les chaînes est bien inférieure à celle des tableaux. Les 500 000 adresses MAC n'occupaient désormais que 9,7 Mo de mémoire. Après la modification, json_decode a été analysé avec succès et la vitesse d'analyse était plus rapide.

À l'origine, macList était un tableau, et les éléments qu'il contient pouvaient être parcourus via foreach. Maintenant, c'est une chaîne. Comment le parcourir ?

Ce n'est pas difficile, vous pouvez utiliser strtok :

$tok = strtok($macList, ',');
while ($tok !== false) {
    $mac = $tok;
    $tok = strtok(',');
}

La difficulté de traversée n'augmente pas beaucoup, non ?

Vous vous demandez peut-être, cette méthode peut traiter de simples tableaux JSON, que devons-nous faire si chaque élément d'un tableau JSON est un objet JSON ?

Nous pouvons construire la chaîne comme ceci :

{
    "list": '{"name":"obj1"}###{"name":"obj2"}###...'
}

La chaîne est constituée de petits JSON, séparés par la marque spéciale ###. Lors de l'analyse, séparez les objets JSON selon des balises spéciales, puis utilisez json_decode pour les analyser un par un :

$tok = strtok($objectList, '###'); // 按###切割
while ($tok !== false)
{
    $objectStr = $tok;
     // 每切割出一个JSON对象就解码
    $object = json_decode($objectStr, true);
    $tok = strtok('###');
}

Vous pouvez également créer votre propre méthode d'encodage/analyse de cette très longue chaîne. Bref, le but ultime est d'éviter. json_decode lors du décodage Un très grand tableau est généré pendant le processus.

À travers cet article, vous devriez avoir un aperçu de la capacité de PHP Array à consommer de la mémoire. Le remplacement des tableaux en JSON par des représentations sous forme de chaîne peut économiser beaucoup de mémoire. J'ai également exécuté des données comparatives pour votre référence :

Parsing de 500 000 MAC :

保存MAC地址方式 数组方式 字符串方式
JSON文件大小 9.6M 8.6M(每个元素省了一对引号)
平均内存占用 72.4M 8.7M
平均json_decode解析时间 0.73s 0.41s

Parsing de 1 million de MAC :

保存MAC地址方式 数组方式 字符串方式
JSON文件大小 20M 18M
平均内存占用 204.6M 54.2M
平均json_decode解析时间 1.61s 0.81s

Parsing de 2 millions de MAC :

保存MAC地址方式 数组方式 字符串方式
JSON文件大小 40M 36M
平均内存占用 409.0M 108.2M
平均json_decode解析时间 3.05s 1.53s

Apprentissage recommandé : Tutoriel vidéo PHP

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer