到底怎么理解php的生成器-Generator

发布于 2019-12-02 10:40:12

今天在了解think-orm的时候看到有个游标查询,里面讲到利用了php的生成器特性,可以大幅减少数据查询时的开销问题.
所以想知道php的generator是什么?是如何减少系统性能开销的.

查看更多

浏览量
2614
猫哥
猫哥 项目组成员 2019-12-02
希望我的回答能对你有所帮助

深入剖析:生成器关键词yield表示每次生成一个值并返回,知道下一次迭代在生产下一个值;php在使用生成器的时候会返回一个Generator类的对象,对该对象的每次迭代,Generator实例都会计算出下一次需要迭代的值,直到不再产生新值为止.

这个的作用就是,你不论迭代循环多少次,每次都只有一个值存放在内存中,从而提供性能.

在回过头来看thinkphp6的**游标查询`,

$cursor = Db::table('user')->where('status', 1)->cursor();
foreach($cursor as $user){
    echo $user['name'];
}

变量$cursor其实是一个Generator对象,对他每进行一次foreach,才会去获取一条用户数据$user,而不是一次性的将所有数据获取出来.

4 个回答
猫哥
猫哥 项目组成员 2019-12-02
希望我的回答能对你有所帮助

原理说明

//普通函数
function xrange($num) {
    $data = [];
    for($i=0;$i<$num;$i++){
        $data[] = time();
    }
    return $data;
}
$result = xrange(1000);
foreach($result as $val){
    sleep(1);
    echo $val.'<br/>';
}

这个普通的函数返回一个要求长度的时间内容数组,假设$num=100万,那$data数组就会是一个拥有100万的键值临时存放在内存中的数据,这回占用很大的内存空间,并占用处理时间.

//生成器方式
function xrange($num) {
    for($i=0;$i<$num;$i++){
        yield time(); //这里的关键词`yield`很重要,它返回一个生成器的对象实例.
    }
}

这个代码同样进行如上的调用,发现结果是不一样的.我们来比较两次的实现过程.

  • 未使用生成器时,xrange函数的结果被全部放到了$data中返回,所以foreach的是一个固定的数组.
  • 使用生成器时,xrange函数返回的值不是一次性生成的,没foreach调用一次,for才执行一次,由于中间sleep了1秒,所以显示的是一个不断变化的数据信息.
猫哥
猫哥 项目组成员 2019-12-02
希望我的回答能对你有所帮助

结论:生成器的优点

  • 节省大量内存,提升性能.
  • 适合计算大量的数据

主要应用方向:读取大量数据信息

猫哥
猫哥 项目组成员 2019-12-02
希望我的回答能对你有所帮助

有关生成器的高级应用-协程
在PHP中使用协程实现多任务调度

学习
记录

发布
问题

分享
好友

手机
浏览

扫码手机浏览