在驾驶方面,速度并不会决定一切。但是在网络上,速度至关重要。你的应用程序越快,用户体验就越好。好吧,这时候有人就奇怪了,本文是关于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调用它,然后再次运行它。但是,这次,我们将创建一个生成器函数。

<?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

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

深入了解PHP的生成器的更多相关文章

  1. 介绍一款原创的四则运算算式生成器:CalculateIt2

    家里小朋友读一年级了,最近每天都有一些10以内的加减法口算练习,作为程序员爸爸,自然也是想办法能够偷懒,让电脑出题,给小朋友做些练习.于是,自己在业余时间开发了一个四则运算算式生成器,名为:Calcu ...

  2. 每天一个设计模式-7 生成器模式(Builder)

    每天一个设计模式-7 生成器模式(Builder) 一.实际问题 在讨论工厂方法模式的时候,提到了一个导出数据的应用框架,但是并没有涉及到导出数据的具体实现,这次通过生成器模式来简单实现导出成文本,X ...

  3. Objective-C 生成器模式 -- 简单实用和说明

    1.生成器模式的定义 将一个复杂的对象的构件与它的表示分离,使得同样的构建过程可以创建不同的表示 2.生成器模式的UML Builder :生成器接口,定义创建一个Product各个部件的操作 Con ...

  4. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(25)-权限管理系统-系统管理员(附生成器)

    系列目录 这一节我们要着手建立系统管理员表,但发布之前,我先发布一个代码生成器给大家先用着. 这个生成器是为这个项目而生的,理论不能用于其他项目,而且写得比较潦草,但能用 下载地址 有兴趣要生成器源码 ...

  5. Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化

    本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解 ...

  6. ES6笔记(5)-- Generator生成器函数

    系列文章 -- ES6笔记系列 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还 ...

  7. C#/ASP.NET完善的DBHelper,配套Model生成器

    支持Oracle.MSSQL.MySQL.SQLite四种数据库,支持事务,支持对象关系映射:已在多个项目中实际使用. 没有语法糖,学习成本几乎为0,拿来即用. DBHelper类完整代码: usin ...

  8. Python 生成器与迭代器 yield 案例分析

    前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天.然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头.).然后只能 花点 ...

  9. Mockjs,模拟数据生成器

    (推荐使用)Mock.js是一款模拟数据生成器,旨在帮助前端攻城师独立于后端进行开发,帮助编写单元测试. 提供了以下模拟功能: 1. 根据数据模板生成模拟数据. 2. 模拟Ajax请求,生成并返回模拟 ...

  10. GUID生成器

    这个GUID生成器是一个小巧的软件,属于笔者在空余时间开发的. http://pan.baidu.com/s/1sk6VGpn

随机推荐

  1. opencv C++图像读取

    int main(){ cv::Mat img=cv::imread("/home/nan/图片/highdeepth/starry.jpg",cv::IMREAD_REDUCED ...

  2. Redis快照原理详解

    本文对Redis快照的实现过程进行介绍,了解Redis快照实现过程对Redis管理很有帮助. Redis默认会将快照文件存储在Redis当前进程的工作目录中的dump.rdb文件中,可以通过配置dir ...

  3. 虚拟机 VMware 设置VMWARE通过桥接方式使用主机无线网卡上网

    环境:WIN7旗舰版,台式机,U盘无线上网卡. 虚拟软件:VMware9.0,虚拟系统:CentOS6.4 需要实现虚拟机以独立机形式工作和上网. 先介绍一下VMware网络设置的三种方式 1 Hos ...

  4. android handle详解

    我们来看一个简单的代码: package com.mly.panhouye.handlerdemo; import android.content.Intent; import android.os. ...

  5. 关于html属性中onSubmit事件属性的使用

    看到一段onSubmit事件属性的例子,如下: <!DOCTYPE html> <html> <head> <script> function vali ...

  6. Selenium+java - Edge浏览器启动

    写在前面 随着win10系统的普及,使得Edge浏览器得到广泛使用.从自动化角度看,自然微软也一直不断提供着支持服务,系统版本更新,对应的Edge浏览器版本也在更新,当然对应的驱动版本也会发生变化. ...

  7. GCC编译和链接过程

    GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分.GCC原本作为GNU操作 ...

  8. MongoDB快速入门教程 (3.2)

    3.2.索引 索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,建立索引,通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条 ...

  9. 集群搭建完成简要测试集群(性能)带宽与IOPS

    集群搭建好之后网络,raid卡策略,磁盘都会影响集群的性能.为了避免因上述问题使得集群的性能受到影响,我们依次进行测试,最后得到基本的集群性能. 网络 首先是网络,ceph集群一大堆让人摸不着头脑的问 ...

  10. (私人收藏)[开发必备]最全Java离线快速查找手册(可查询可学习,带实例)

    (私人收藏)[开发必备]最全Java离线快速查找手册(可查询可学习,带实例) https://pan.baidu.com/s/1L54VuFwCdKVnQGVc8vD1TQnwmj java手册 Ja ...