php中 yield生成器的简单使用

原因: 为了防止php变量太大(比如sql出查询10w条数据放入数组)导致内存溢出。

 

传统解决方法: 内存溢出时报 **Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)** 错误,以往通过php.ini或者ini_set() 来设置一个进程的更大内存,虽然能解决大内存问题但不利于接口的性能。

 

yield原理:假如有100条数据 用foreach就是一次性把数据放到一个数组,内存长度占100。 用yield是一条一条放进去,而且每次放完一条就“销毁”,然后总内存是一条,内存长度只占1可以想象yield有点类似 return

 

 

常见使用场景

用法1,处理一个返回值或一个键值对

// 传统
function
createRange($number){ $data = []; for($i=1;$i<$number;$i++){ $data[$i] = time(); } return $data; }
// yield
function
createRange($number){ for($i=1;$i<$number;$i++){ yield $i => time(); } } $result = createRange(10); // 这里返回生成器对象(里面是我们要的数组data,但内存只占1) foreach($result as $k=>$value){echo $value.$k; }

 

 

用法2,处理sql查询出来的数组

public static function yieldData($data){
    foreach ($data as $datum){
        yield $datum;
    }
}

$res = Db()->select();
$list = self::yieldData($res);

// 逻辑处理
foreach($list as $k => &$v){}

// 导出等等
Common::csv($list)

 

用法3,文件读取/导入功能

function readTxt($path)
{
    $handle = fopen($path, 'rb');
    while (feof($handle)===false) {
        yield fgets($handle);
    }
    fclose($handle);
}

foreach (readTxt() as $key => $value) {
   // 逻辑处理
}

 

总结

yield生成器允许你 在 foreach 代码块中写代码来迭代一组数据,而不需要在内存中创建一个数组,极大提高了进程的内存使用率

 

其它细节可参考:https://segmentfault.com/a/1190000012334856

posted @ 2022-04-19 11:27  jaychou、  阅读(400)  评论(0编辑  收藏  举报