详解PHP中被忽略的性能优化利器:生成器-php教程

资源魔 22 0

假如是做Python或许其余言语的小同伴,关于天生器应该没有生疏。但不少PHP开发者或者都没有晓得天生器这个性能,多是由于天生器是PHP 5.5.0才引入的性能,也能够是天生器作用没有是很显著。然而,天生器性能确实十分有用。

优点

间接讲概念预计你听完仍是一头雾水,以是咱们先来讲说优点,兴许能勾起你的兴味。那末天生器有哪些优点,以下:

  • 天生器会对PHP使用的功能有十分年夜的影响
  • PHP代码运转时节流年夜量的内存
  • 比拟适宜较量争论年夜量的数据

那末,这些神秘的性能终究是若何做到的?咱们先来举个例子。

概念引入

起首,放下天生器概念的包袱,来看一个简略的PHP函数:

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

这是一个十分常见的PHP函数,咱们正在解决一些数组的时分常常会应用。这里的代码也十分简略:

  1. 咱们创立一个函数。
  2. 函数内蕴含一个for轮回,咱们轮回的把以后工夫放到$data外面
  3. for轮回执行终了,把$data前往进来。

上面没完,咱们持续。咱们再写一个函数,把这个函数的前往值轮回打印进去:

$result = createRange(10); // 这里挪用下面咱们创立的函数
foreach($result as $value){
    sleep(1);//这里进展1秒,咱们后续有用
    echo $value.'<br />';
}复制代码

咱们正在阅读器外面看一下运转后果:

![](https://picb.zhimg.com/80/v2-3620f3d46bb5b49e53ca47891ea1fd5a_720w.jpg)

这里十分完满,不任何成绩。(当然sleep(1)成果你们看没有进去)

考虑一个成绩

咱们留意到,正在挪用函数createRange的时分给$number的传值是10,一个很小的数字。假定,如今通报一个值10000000(1000万)。

那末,正在函数createRange外面,for轮回就需求执行1000万次。且有1000万个值被放到$data外面,而$data数组正在是被放正在内存内。以是,正在挪用函数时分会占用年夜量内存。

这里,天生器就能够大显神通了。

创立天生器

咱们间接修正代码,你们留意察看:

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

看下这段以及刚刚很像的代码,咱们删除了了数组$data,并且也不前往任何内容,而是正在time()以前应用了一个要害字yield

应用天生器

咱们再运转一下第二段代码:

$result = createRange(10); // 这里挪用下面咱们创立的函数
foreach($result as $value){
    sleep(1);
    echo $value.'<br />';
}复制代码

![](https://pic2.zhimg.com/80/v2-9c08f2d01f7a68736f45ffa3d3934cc5_720w.jpg)

咱们奇观般的发现了,输入的值以及第一次不应用天生器的纷歧样。这里的值(工夫戳)两头距离了1秒。

这里的距离一秒其实就是sleep(1)酿成的结果。然而为何第一次不距离?那是由于:

  • 未应用天生器时:createRange函数内的for轮回后果被很快放到$data中,而且立刻前往。以是,foreach轮回的是一个固定的数组。
  • 应用天生器时:createRange的值没有是一次性疾速天生,而是依赖于foreach轮回。foreach轮回一次,for执行一次。

到这里,你应该对天生器有点儿眉目。

深化了解天生器

代码分析

上面咱们来关于刚刚的代码进行分析。

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

$result = createRange(10); // 这里挪用下面咱们创立的函数
foreach($result as $value){
    sleep(1);
    echo $value.'<br />';
}复制代码

咱们来复原一下代码执行进程。

  1. 起首挪用createRange函数,传入参数10,然而for值执行了一次而后中止了,而且通知foreach第一次轮回能够用的值。
  2. foreach开端对$result轮回,出去起首sleep(1),而后开端应用for给的一个值执行输入。
  3. foreach预备第二次轮回,开端第二次轮回以前,它向for轮回又申请了一次。
  4. for轮回于是又执行了一次,将天生的工夫戳通知foreach.
  5. foreach拿到第二个值,而且输入。因为foreachsleep(1),以是,for轮回提早了1秒天生以后工夫

以是,整个代码执行中,始终只有一个记载值参加轮回,内存中也只有一条信息。

无论开端传入的$number有多年夜,因为其实不会立刻天生一切后果集,以是内存始终是一条轮回的值。

概念了解

到这里,你应该曾经大略了解甚么是天生器了。上面咱们来讲下天生器原理。

起首明白一个概念:天生器yield要害字没有是前往值,他的业余术语叫产出值,只是天生一个值

那末代码中foreach轮回的是甚么?实际上是PHP正在应用天生器的时分,会前往一个Generator类的工具。foreach能够对该工具进行迭代,每一一次迭代,PHP会经过Generator实例较量争论出下一次需求迭代的值。这样foreach就晓得下一次需求迭代的值了。

并且,正在运转中for轮回执行后,会立刻中止。期待foreach下次轮回时分再次以及for索要下次的值的时分,for轮回才会再执行一次,而后立刻再次中止。直到没有餍足前提没有执行完结。

实际开发使用

不少PHP开发者没有理解天生器,其实次要是没有理解使用畛域。那末,天生器正在实际开发中有哪些使用?

读取超年夜文件

PHP开发不少时分都要读取年夜文件,比方csv文件、text文件,或许一些日记文件。这些文件假如很年夜,比方5个G。这时候,间接一次性把一切的内容读取到内存入彀算没有太事实。

这里天生器就能够派上用场啦。简略看个例子:读取text文件

![](https://pic1.zhimg.com/80/v2-2d6fb1058b39008fbe4e5363e485e9a2_720w.jpg)

咱们创立一个text文本文档,并正在此中输出几行文字,树模读取。

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

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

    fclose($handle);
}

foreach (readTxt() as $key => $value) {
    # code...
    echo $value.'<br />';
}复制代码

![](https://pic4.zhimg.com/80/v2-2bbdc40ebf8f1aeedf2aa0c472811c77_720w.jpg)

经过上图的输入后果咱们能够看出代码齐全失常。

然而,面前的代码执行规定却一点儿也纷歧样。应用天生器读取文件,第一次读取了第一行,第二次读取了第二行,以此类推,每一次被加载到内存中的文字只有一行,年夜年夜的减小了内存的应用。

这样,即便读取上G的文本也不必担忧,齐全能够像读取很小文件同样编写代码。

想理解更多编程学习,敬请存眷php培训栏目!

以上就是详解PHP中被疏忽的功能优化利器:天生器的具体内容,更多请存眷资源魔其它相干文章!

标签: php php开发教程 php开发资料 php开发自学 生成器

抱歉,评论功能暂时关闭!