Understanding PHP Generators(译)Understanding PHP Generators

PHP Generators

Understanding PHP Generators

为什么需要谈论Generators,作为互联网应有,更快的速度意味着更好的用户体验,而Generators则是php中解决速度和内存的杀手锏

原文

代码

What are PHP Generators?

在php5.5中加入,generators解决了在一个loop中不需要在内存中构建整个数组的问题,可能这么说还不是很明了

talk is cheap, show me the code

我们来看下一段代码,保存为文件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>";
}

我们可以通过命令快速启动以个server

php -S localhost:8000

如果我们访问http://localhost:8000/generator.php我们会看到下面

Dataset 1 
Dataset 2 
Dataset 3 
Dataset 4 
Dataset 5 
Dataset 6 
Dataset 7 
Dataset 8 
Dataset 9 
Dataset 10 
Dataset 11 
Dataset 12 
Dataset 13 
Dataset 14 

代码很容易理解,也没什么问题,但是如果我们改动下代码:

<?php

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

此时最大数变为了PHP_INT_MAX,再次运行就会出现下面的错误:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 134217736 bytes) in /private/tmp/php-generator/generator.php on line 7

超过最大内存了,此时一个可能的解决方案是修改php.ini 然后增加memory_limit。但是这个真能解决问题吗,我们是否真的希望一个脚本耗尽了我们的内存,显然是no!

Using Generators

我们还是实现同样的功能,这次我们创建一个generator函数

<?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函数,这次我们只是在loop中yield值,yield类似于return,不同之处在于yield只有在被返回的值需要的时候才会产生这个值,不会让整个返回集合都在内存中

此时我们再次访问http://localhost:8000/generator.php,只要给浏览器足够的时间,所有的数据都会返回

Why Do This?

我们的目标是提升速度,但是内存不增加。很多时候,我们在处理log文件的时候,经常会遇到内存耗尽的情况,使用generator就能很好的解决

Returning Keys

除了返回简单的值,我们还能返回键值对

<?php

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

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

Sending Values to Generator

我们除了可以从generators中读数据,还能往里面写数据

<?php

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

        if ($injected === 'stop') return;
    }
}
$generator = getRange(PHP_INT_MAX);

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

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

注意: 在generators中使用return,将会退出generator

Don't Misuse Generators

Generators用来高效使用内存,但是使用Generators并不意味着不会出现内存耗尽的情况,如果错误使用的话,也会遇到同样的问题。

Conclusion

Generators给我们提供了无法拒绝的性能提升。大多数时候,我们不需要高性能的服务器来解决问题,需要的这是我们重构下代码。Generators非常棒,我们应该多使用它。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏iOSDevLog

更多关于CocoaScript目录

3686
来自专栏CodingBlock

Android学习笔记(十四)方便实用的首选项-PreferenceActivity

 突然发现已经好多天没更新博客了,最近公司项目正在进行一个大跨度的重构,又碰上有新需求,一连好多天都是很晚才到家。其实这篇博文在草稿箱里面也存了很久了,本来想着...

1997
来自专栏听雨堂

从MapX到MapXtreme2004[2]-图层操作

Mapx中基本的图层操作还是比较简单的,集中在对Layers和Layer的处理上,对别的没有太多要求。   在MapXtreme中,要完成类似功能,发生了一点...

2118
来自专栏哲学驱动设计

OEA 中 WPF 树型表格整体重构

为什么要重构     上两个月主要做了一件事情,那就是把 OEA 框架中的 TreeGrid 控件,从结构上重新设计,并大量重构现有代码。而花较大精力做这件事的...

2046
来自专栏向治洪

MobX 在 React Native开发中的应用

MobX 是一款精准的状态管理工具库,如果你在 React 和 React Native 应用中使用过 Flux、Alt、Redux 和 Reflux,那毫不犹...

5038
来自专栏向治洪

MobX 在 React Native开发中的应用

MobX 是一款精准的状态管理工具库,如果你在 React 和 React Native 应用中使用过 Flux、Alt、Redux 和 Reflux,那毫不犹...

2597
来自专栏前端知识分享

第182天:HTML5——地理定位

HTML5 Geolocation API 用于获得用户的地理位置。 鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的。

2872
来自专栏CRPER折腾记

Angular 2 + 折腾记 :(6) 动手实现只有年月的小组件

这个组件实现并不是很复杂,我会尽量注释; 这货诞生的理由就是项目刚好有一个地方必须只能选择年月,而github上ng2+日期组件都涉及到年月日或时分秒; 效果用...

901
来自专栏程序员的SOD蜜

“老坛泡新菜”:SOD MVVM框架,让WinForms焕发新春

火热的MVVM框架 最近几年最热门的技术之一就是前端技术了,各种前端框架,前端标准和前端设计风格层出不穷,而在众多前端框架中具有MVC,MVVM功能的框架成为耀...

3966
来自专栏我有一个梦想

Python 项目实践一(外星人入侵小游戏)第三篇

接着上节的继续学习, 一 重构:模块game_functions 在大型项目中,经常需要在添加新代码前重构既有代码。重构旨在简化既有代码的结构,使其更容易扩展。...

2999

扫码关注云+社区

领取腾讯云代金券