钱柜娱乐999

卓象程序员:PHP性能优化利器 yield 生成器

08: 39: 05卓翔程序员

直接谈到产量发生器的概念,估计你仍然感到困惑,所以让我们首先谈谈优势,也许会带来你的兴趣。那么发电机有什么优点,如下:

1.生成器对PHP应用程序的性能有很大的影响

2. PHP代码在运行时节省了大量内存

3.更适合计算大量数据

那么这些神奇的功能究竟是如何运作的呢?我们先举一个例子。

概念介绍

函数createRange($ number){?$数据=[];for($ i=0; $ i< $ number; $ i ++){?$数据[]=时间();}?返回$ data;}

这是我们在处理某些数组时经常使用的非常常见的PHP函数。这里的代码也很简单:

1)我们创建一个函数。

2)该函数包含一个?for?循环,我们将当前时间循环到$ data

3)执行for循环并返回?$数据。

以下未结束,让我们继续。让我们编写另一个函数来打印这个函数的返回值:

$结果=createRange(10); //这里我们调用我们在foreach上面创建的函数($ result as $ value){?sleep(1); //暂停1秒钟,我们稍后会用它?echo $ value。' “;}

我们来看看浏览器中的结果:

1565138332976374687.jpg

这里很完美,没有任何问题。 (当然?睡眠(1)效果你看不到)

思考问题

我们注意到在调用函数时传递给?$ number的值?createRange?是10,少数。假设现在传递一个值(1000万)。

然后,在函数?createRange?中,for循环需要执行1000万次。

1000万个值放在?$ data?中,$ data数组放在内存中。因此,调用函数时需要大量内存。这里,可以使用发电机。

创建一个生成器

我们直接修改代码,你注意观察:

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

看看这个和刚刚发生的代码,我们删除了数组?$ data?并且没有返回任何内容,但在?time()之前使用了关键字yield?

使用发电机

让我们再次运行第二段代码:

$结果=createRange(10); //这里我们调用我们在foreach上面创建的函数($ result as $ value){?睡眠(1);echo $ value。'';}}

我们来看看结果:

1565138333239052453.jpg

我们奇迹般地发现输出值与第一次不使用发生器时不同。此处的值(时间戳)以1秒为单位。这里间隔一秒实际上是睡眠(1)的结果?但为什么第一次没有差距呢?那是因为:

1.未使用生成器时:createRange函数内的for循环结果快速放入$ data并立即返回。因此,foreach循环是一个固定的数组。

2.使用生成器时:createRange的值不会立即快速生成,而是取决于foreach循环。 Foreach循环一次,for执行一次。

在这一点上,你应该对发电机有点线索。

深刻理解发电机

我们来看看刚才描述的代码。

函数createRange($ number){?for($ i=0; $ i< $ number; $ i ++){?屈服时间();}} $结果=createRange(10); //这里调用我们在foreach上面创建的函数($ result as $ value){?睡眠(1);echo $ value。'';}}

让我们恢复代码执行过程。

1.首先调用createRange函数,传入参数10,但for值执行一次然后停止,并告诉foreach可以在第一个循环中使用的值。

2.foreach启动$ result循环,首先进入sleep(1),然后开始执行值为for的输出。

3.foreach准备第二个循环,并在开始第二个循环之前再次向for循环请求它。

然后再次执行4.for循环,告诉foreach生成的时间戳。

5. foreach取第二个值并输出。由于foreach中的睡眠(1),for循环被延迟1秒以产生当前时间

信息。

无论传入的$ number循环的值如何。

概念性理解

此时,您应该已经了解了生成器是什么。我们来看看生成器原理

首先明确一个概念:生成器yield关键字不是返回值,他的术语称为输出值,只是生成一个值。

那么代码中的foreach循环是什么?

实际上,当PHP使用生成器时,它将返回Generator类的对象。 Foreach可以迭代对象,每次迭代,PHP都会通过Generator实例计算下一次迭代的值。这样foreach知道下次需要迭代的值。此外,它在运行中执行for循环后立即停止。等待foreach再次循环,并且for part的结尾不会被执行。

实际开发应用

阅读超大文件

PHP开发通常会读取大文件,例如csv文件,文本文件或某些日志文件。这些文件很大,例如5G。此时,将所有内容一次直接读入存储器是不现实的。

这里的发电机可以派上用场。举一个简单的例子:阅读文本文件。

1565138333402528881.jpg

我们创建一个文本文本文档,并在其中输入几行文本来演示阅读。

<phpheader(''content-type: text/html; charset=utf-8''); function readTxt(){?#code .$ handle=fopen('''','rb');while(feof($ handle)===false){?#code . FGETS($处理);}?fclose($ handle);} foreach(readTxt()as $ key=> $ value){?#code .echo $ value。'';}}

1565138333495973409.jpg

从上图的输出中,我们可以看到代码完全正常。

但是,它背后的代码执行规则并不相同。使用生成器读取文件,第一行是第一次读取,第二行是第二次读取,依此类推,每次加载到内存中的文本只有一行,大大减少了内存。使用。

这样,您不必担心阅读G上的文本。您可以像读取小文件一样编写代码。

1565138333591592502.png

直接谈到产量发生器的概念,估计你仍然感到困惑,所以让我们首先谈谈优势,也许会带来你的兴趣。那么发电机有什么优点,如下:

1.生成器对PHP应用程序的性能有很大的影响

2. PHP代码在运行时节省了大量内存

3.更适合计算大量数据

那么这些神奇的功能究竟是如何运作的呢?我们先举一个例子。

概念介绍

函数createRange($ number){?$数据=[];for($ i=0; $ i< $ number; $ i ++){?$数据[]=时间();}?返回$ data;}

这是我们在处理某些数组时经常使用的非常常见的PHP函数。这里的代码也很简单:

1)我们创建一个函数。

2)该函数包含一个?for?循环,我们将当前时间循环到$ data

3)执行for循环并返回?$数据。

以下未结束,让我们继续。让我们编写另一个函数来打印这个函数的返回值:

$结果=createRange(10); //这里我们调用我们在foreach上面创建的函数($ result as $ value){?sleep(1); //暂停1秒钟,我们稍后会用它?echo $ value。' “;}

我们来看看浏览器中的结果:

1565138332976374687.jpg

这里很完美,没有任何问题。 (当然?睡眠(1)效果你看不到)

思考问题

我们注意到在调用函数时传递给?$ number的值?createRange?是10,少数。假设现在传递一个值(1000万)。

然后,在函数?createRange?中,for循环需要执行1000万次。

1000万个值放在?$ data?中,$ data数组放在内存中。因此,调用函数时需要大量内存。这里,可以使用发电机。

创建一个生成器

我们直接修改代码,你注意观察:

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

看看这个和刚刚发生的代码,我们删除了数组?$ data?并且没有返回任何内容,但在?time()之前使用了关键字yield?

使用发电机

让我们再次运行第二段代码:

$结果=createRange(10); //这里我们调用我们在foreach上面创建的函数($ result as $ value){?睡眠(1);echo $ value。'';}}

我们来看看结果:

1565138333239052453.jpg

我们奇迹般地发现输出值与第一次不使用发生器时不同。此处的值(时间戳)以1秒为单位。这里间隔一秒实际上是睡眠(1)的结果?但为什么第一次没有差距呢?那是因为:

1.未使用生成器时:createRange函数内的for循环结果快速放入$ data并立即返回。因此,foreach循环是一个固定的数组。

2.使用生成器时:createRange的值不会立即快速生成,而是取决于foreach循环。 Foreach循环一次,for执行一次。

在这一点上,你应该对发电机有点线索。

深刻理解发电机

我们来看看刚才描述的代码。

函数createRange($ number){?for($ i=0; $ i< $ number; $ i ++){?屈服时间();}} $结果=createRange(10); //这里调用我们在foreach上面创建的函数($ result as $ value){?睡眠(1);echo $ value。'';}}

让我们恢复代码执行过程。

1.首先调用createRange函数,传入参数10,但for值执行一次然后停止,并告诉foreach可以在第一个循环中使用的值。

2.foreach启动$ result循环,首先进入sleep(1),然后开始执行值为for的输出。

3.foreach准备第二个循环,并在开始第二个循环之前再次向for循环请求它。

然后再次执行4.for循环,告诉foreach生成的时间戳。

5. foreach取第二个值并输出。由于foreach中的睡眠(1),for循环被延迟1秒以产生当前时间

信息。

无论传入的$ number循环的值如何。

概念性理解

此时,您应该已经了解了生成器是什么。我们来看看生成器原理

首先明确一个概念:生成器yield关键字不是返回值,他的术语称为输出值,只是生成一个值。

那么代码中的foreach循环是什么?

实际上,当PHP使用生成器时,它将返回Generator类的对象。 Foreach可以迭代对象,每次迭代,PHP都会通过Generator实例计算下一次迭代的值。这样foreach知道下次需要迭代的值。此外,它在运行中执行for循环后立即停止。等待foreach再次循环,并且for part的结尾不会被执行。

实际开发应用

阅读超大文件

PHP开发通常读取大型文件,如csv文件、文本文件或某些日志文件。这些文件很大,例如5g。此时,一次直接将所有内容读取到内存中是不现实的。

在这里发电机可以派上用场。举个简单的例子:阅读文本文件。

0×251e

我们创建一个文本文档,并在其中输入几行文本来演示阅读。

&?phphpheader(''content-type: text/html;charset=utf-8'');函数readtxt()?代码…?$handle=fopen('''rb');而(feof($handle)==false)?#代码…?fgets($handle);}?fclose($handle);foreach(readtxt()as$key=>;$value)?代码…?回声$value。';

0×251f

从上图的输出可以看出,代码是完全正常的。

但是,它背后的代码执行规则并不相同。使用生成器读取文件,第一行是第一次读取,第二行是第二次读取,依此类推,每次加载到内存中的文本只有一行,大大减少了内存。使用。

这样,您不必担心阅读G上的文本。您可以像读取小文件一样编写代码。

1565138333591592502.png