深刻了解PHP的生成器

在驾驶方面,速度并不会决定一切。可是在网络上,速度相当重要。你的应用程序越快,用户体验就越好。好吧,这时候有人就奇怪了,本文是关于PHP 生成器的,那么为何咱们要谈论速度呢?很快你就会发现,生成器在速度和内存管理上产生了巨大的差别。php

PHP生成器是什么?

在5.5版的PHP中添加了生成器,这些生成器提供了一种简单的方法来遍历数据而无需在内存中构建数组的功能。仍是有点困惑吗?那举一个例子是显示生成器运行状况的好方法。数据库

首先,让咱们快速建立一个咱们将在本教程中使用的generator.php文件。建立文件后,咱们添加一小段代码。数组

<?php

function getRange ($max = 10) {
    $array = [];

    for ($i = 1; $i < $max; $i++) {
        $array[] = $i;
    }

    return $array;
}

foreach (getRange(15) as $range) {
    echo "Dataset {$range} <br>";
}

 

咱们能够在建立generator.php文件的目录中快速启动内置的PHP服务器:浏览器

php -S localhost:8000

 

因此若是咱们去 http:// localhost:8000 / generator.php,咱们应该会获得这样的东西。服务器

该代码几乎是不言自明的,并且看起来绝对不是不少。可是,若是咱们返回代码并进行一些更改,以下网络

<?php

foreach (getRange(PHP_INT_MAX) as $range) {
    echo "Dataset {$range} <br>";
}

 

如今,生成数字的上限(最大值)是PHP_INT_MAX,这是你的PHP版本能够达到的最大数字。完成此操做后,转到浏览器并刷新。可是此次,你会注意到此次有一些不一样的东西。生成器脚本引起警告错误。函数


好吧,这很惋惜,PHP用尽了内存。我想到的解决方案可能包括进入php.ini以及增长memory_limit的上限。让咱们问问本身这些问题,这真的有效吗?咱们是否要一个脚原本占用服务器的全部内存?答案是否认的。这是无效的,而且咱们不但愿单个脚本用完咱们全部的内存。性能

使用生成器

让咱们定义上面的相同函数,使用相同的值PHP_INT_MAX调用它,而后再次运行它。可是,此次,咱们将建立一个生成器函数。spa

<?php

function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        yield $i;
    }
}

foreach (getRange(PHP_INT_MAX) as $range) {
    echo "Dataset {$range} <br>";
}

 

剖析getRange函数,这一次,咱们仅遍历值和yield输出。yield相似于return,由于它也是从函数返回值,可是惟一的区别是yield仅在须要时才返回值,而且不会尝试将整个数据集保留在内存中。日志

若是转到浏览器,应该会看到页面上显示的数据。给定适当的时间,浏览器最终将显示数据。

注意:只能经过函数使用生成器。

为何这样作?

有时,咱们可能想解析大型数据集(能够是日志文件),或者对大型数据库结果执行计算等。咱们不但愿这样的操做占用全部内存。咱们应该尝试尽量地节省内存。数据没必要必定很大-无论数据集多么小,生成器都是有效的。别忘了,咱们的目标是使用更少的内存来提升速度。

返回键

有时,只有当数据是基于key-value时,咱们的数据才有意义。使用生成器时,咱们能够产生这样的键值对。

<?php

function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        $value = $i * mt_rand();

        yield $i => $value;
    }
}

 

而后,咱们能够像使用任何这样的数组同样继续使用该键值对。

<?php

foreach (getRange(PHP_INT_MAX) as $range => $value) {
    echo "Dataset {$range} has {$value} value<br>";
}

 

将值发送到生成器

生成器也能够接受值。这意味着生成器容许咱们将值注入到它们中,多是做为命令或其余方式。例如,咱们能够向生成器发送一个值,告诉它中止执行或更改输出。使用上面的getRange函数,咱们能够作到这一点。

<?php

function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        $injected = yield $i;

        if ($injected === 'stop') return;
    }
}

 

要发送注入该值,咱们能够这样作。

<?php

$generator = getRange(PHP_INT_MAX);

foreach ($generator as $range) {
    if ($range === 10000) {
        $generator->send('stop');
    }

    echo "Dataset {$range} <br>";
}

 

注意:在生成器中使用return会中断生成器功能。

不要滥用生成器

使用PHP_INT_MAX有点麻烦。对我来讲,PHP_INT_MAX是2147483647,即:

二十一亿四千七百四十八万三千六百四十七

生成器应该是内存有效的。这并不意味着若是使用不当,它们不会引发他们试图解决的相同问题。

结论

生成器提供了咱们难以忽视的性能提高。大多数时候,咱们不须要强大的服务器来处理咱们的代码。咱们只须要作一些重构。生成器颇有用,咱们应该更多地使用它们。

原文地址:https://scotch.io/tutorials/understanding-php-generators

今日就分享到这啦,若是任何问题或者建议,欢迎留言交流。

相关文章
相关标签/搜索