Maison >développement back-end >tutoriel php >Outils d'optimisation des performances en PHP que vous pourriez négliger : contenu lié au générateur

Outils d'optimisation des performances en PHP que vous pourriez négliger : contenu lié au générateur

jacklove
jackloveoriginal
2018-07-06 17:51:071326parcourir

L'optimisation des performances est une partie essentielle de notre développement. L'article suivant vous présente principalement l'outil d'optimisation des performances en PHP que vous pourriez ignorer : les informations pertinentes du générateur. L'article le présente en détail à travers un exemple de code. dans le besoin peuvent s'y référer, jetons un coup d'œil ci-dessous.

Préface

Si vous travaillez en Python ou dans d'autres langages, vous devez être familier avec les générateurs. Cependant, de nombreux développeurs PHP peuvent ne pas connaître la fonction générateur. Cela peut être dû au fait que le générateur est une fonction introduite dans PHP 5.5.0, ou que la fonction du générateur n'est pas très évidente. Cependant, la fonction générateur est vraiment utile.

Dans quelles circonstances rencontrerez-vous des problèmes de performances PHP ?

1 : Utilisation inappropriée de la syntaxe PHP.

2 : Utiliser le langage PHP pour faire des choses pour lesquelles il n'est pas doué.

3 : Le service connecté en langage PHP n'est pas bon.

4 : Les propres défauts de PHP (des choses que PHP lui-même ne peut pas faire).

5 : Un problème dont on ne connaît même pas l’existence ? (Pour explorer, analyser et trouver des solutions et améliorer le niveau de développement).

Avantages

Si je parle directement du concept, je suppose que vous serez toujours confus après l'avoir entendu, alors parlons-en sur les avantages d'abord, cela peut peut-être piquer votre intérêt. Alors quels sont les avantages des générateurs, comme suit :

  • Les générateurs auront un grand impact sur les performances des applications PHP

  • Lorsque le code PHP fonctionne Économisez beaucoup de mémoire

  • Plus adapté au calcul de grandes quantités de données

Alors, comment ces fonctions magiques sont-elles réalisées ? Donnons d'abord un exemple.

Introduction au concept

Tout d'abord, mettons de côté le bagage du concept de générateur et examinons une simple fonction PHP :

function createRange($number){
 $data = [];
 for($i=0;$i<$number;$i++){
  $data[] = time();
 }
 return $data;
}

Il s'agit d'une fonction PHP très courante que nous utilisons souvent lors du traitement de certains tableaux. Le code ici est également très simple :

  • On crée une fonction.

  • La fonction contient une boucle for. Nous bouclons l'heure actuelle dans $data

  • Une fois la boucle for exécutée, $data Revenir en arrière. dehors.

Ce n’est pas encore fini, continuons. Écrivons une autre fonction et imprimons la valeur de retour de cette fonction dans une boucle :

$result = createRange(10); // 这里调用上面我们创建的函数
foreach($result as $value){
 sleep(1);//这里停顿1秒,我们后续有用
 echo $value.&#39;<br />&#39;;
}

Jetons un coup d'œil aux résultats exécutés dans le navigateur :

Cet endroit est parfait, aucun problème. (Bien sûr, vous ne pouvez pas voir l'effet du sommeil(1))

Réfléchissez à une question

Nous avons remarqué que lors de l'appel de la fonction createRange La valeur passée à $number est 10, un très petit nombre. Supposons que nous transmettions maintenant une valeur de 1 000 000 (10 millions).

Ensuite, dans la fonction createRange, la boucle for doit être exécutée 10 millions de fois. Et 10 millions de valeurs sont placées dans $data, et le tableau $data est placé en mémoire. Par conséquent, beaucoup de mémoire sera occupée lors de l’appel de fonctions.

Ici, le générateur peut entrer en jeu.

Créer un générateur

Nous modifions le code directement, veuillez faire attention :

function createRange($number){
 for($i=0;$i<$number;$i++){
  yield time();
 }
}

Regardez ce code qui est très similaire à celui de tout à l'heure. Nous avons supprimé le tableau $data et n'avons rien renvoyé. À la place, nous avons utilisé le mot-clé rendement.

Utiliser le générateur

Exécutons à nouveau le deuxième morceau de code :

$result = createRange(10) / / Ici, nous appelons la fonction que nous avons créée ci-dessus

foreach($result as $value){
sleep(1);
echo $value.'df250b2156c434f3390392d09b1c9563';
}


Nous avons miraculeusement découvert que la valeur de sortie est différente de la première fois sans utiliser le générateur. Les valeurs (horodatages) ici sont séparées de 1 seconde.

L'intervalle d'une seconde ici est en fait le résultat du sommeil(1). Mais pourquoi n’y a-t-il pas d’écart la première fois ? En effet :

  • Lorsque le générateur n'est pas utilisé : le résultat de la boucle for dans la fonction createRange est rapidement placé dans $data et renvoyé immédiatement. Par conséquent, la boucle foreach est un tableau fixe.

  • Lors de l'utilisation d'un générateur : la valeur de createRange n'est pas générée rapidement d'un coup, mais repose sur la boucle foreach. foreach boucle une fois et for est exécuté une fois.

À ce stade, vous devriez avoir une idée du générateur.

Compréhension approfondie des générateurs

Analyse de code

Suivons Analysons le code tout à l'heure.

function createRange($number){
 for($i=0;$i<$number;$i++){
  yield time();
 }
}
$result = createRange(10); // 这里调用上面我们创建的函数
foreach($result as $value){
 sleep(1);
 echo $value.'
'; }

Restaurons le processus d'exécution du code.

  • 首先调用createRange函数,传入参数10,但是for值执行了一次然后停止了,并且告诉foreach第一次循环可以用的值。

  • foreach开始对$result循环,进来首先sleep(1),然后开始使用for给的一个值执行输出。

  • foreach准备第二次循环,开始第二次循环之前,它向for循环又请求了一次。

  • for循环于是又执行了一次,将生成的时间戳告诉foreach.

  • foreach拿到第二个值,并且输出。由于foreach中sleep(1),所以,for循环延迟了1秒生成当前时间

所以,整个代码执行中,始终只有一个记录值参与循环,内存中也只有一条信息。

无论开始传入的$number有多大,由于并不会立即生成所有结果集,所以内存始终是一条循环的值。

概念理解

到这里,你应该已经大概理解什么是生成器了。下面我们来说下生成器原理。

首先明确一个概念:生成器yield关键字不是返回值,他的专业术语叫产出值,只是生成一个值

那么代码中foreach循环的是什么?其实是PHP在使用生成器的时候,会返回一个Generator类的对象。foreach可以对该对象进行迭代,每一次迭代,PHP会通过Generator实例计算出下一次需要迭代的值。这样foreach就知道下一次需要迭代的值了。

而且,在运行中for循环执行后,会立即停止。等待foreach下次循环时候再次和for索要下次的值的时候,for循环才会再执行一次,然后立即再次停止。直到不满足条件不执行结束。

实际开发应用

很多PHP开发者不了解生成器,其实主要是不了解应用领域。那么,生成器在实际开发中有哪些应用?

读取超大文件

PHP开发很多时候都要读取大文件,比如csv文件、text文件,或者一些日志文件。这些文件如果很大,比如5个G。这时,直接一次性把所有的内容读取到内存中计算不太现实。

这里生成器就可以派上用场啦。简单看个例子:读取text文件

我们创建一个text文本文档,并在其中输入几行文字,示范读取。

<?php
header("content-type:text/html;charset=utf-8");
function readTxt()
{
 # code...
 $handle = fopen("./test.txt", &#39;rb&#39;);

 while (feof($handle)===false) {
  # code...
  yield fgets($handle);
 }

 fclose($handle);
}

foreach (readTxt() as $key => $value) {
 # code...
 echo $value.&#39;<br />&#39;;
}


通过上图的输出结果我们可以看出代码完全正常。

但是,背后的代码执行规则却一点儿也不一样。使用生成器读取文件,第一次读取了第一行,第二次读取了第二行,以此类推,每次被加载到内存中的文字只有一行,大大的减小了内存的使用。

这样,即使读取上G的文本也不用担心,完全可以像读取很小文件一样编写代码。

总结

您可能感兴趣的文章:

Laravel框架中composer自动加载的实现详解

PHP服务端环境搭建的图文教程

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn