php yield的了解及使用

3,294 阅读2分钟
  1. ✨前言

    最近需要把一批地理数据存到redis上面,方便作为一个地理范围检索的用途使用,但是奈何数据量几十万级的,动不动PHP就会报内存溢出了,这样子还得找办法解决

  2. yield的出现

    在我苦思一顿之后(其实是摸鱼摸出来的),发现了PHP竟然有如此神功(yield),可以助我羽化登仙,呸呸呸。

  3. 实践是检验真理的唯一标注

  • 本质  其实yield的实质可以看作一个单向的链表,每一次取完数据就会往后移,直到到达了末尾


    输出结果:

    current:0 
    key:0 
    next: 
    valid:1 
    current:1
    

    当迭代生成器遍历完一次之后,想要继续遍历,会抛出异常,由此证明生成器在遍历完一次之后,就会失去了他原本的作用


    0  
    1  
    2  
    3  
    4  
    Fatal error: Uncaught Exception: Cannot traverse an already closed generator in C:\xampp\htdocs\test.php:32 Stack trace: #0 {main} thrown in C:\xampp\htdocs\test.php on line 32
  • 占用内存 回到本次解决问题的中心点,就是要解决大量数据导致PHP内存溢出的问题,下面我们来做一下简单的试验


    实验结果:

    384056b 
    781032b 
    384056b 
    4578040b
    

    结果表明,生成器只是占用了存储自生对象的内存,无论数据再多,占用的内存不变,而一般的返回数组形式会导致数据越多占用的内存越高

  • 结合实际情况分析 也有人会想到,那放在yield里面的操作换成读数据库或者调用其他接口获取数据再返回,会不会在遍历的时候,每遍历一次就会读一次库或者调一次接口?


    实验结果:生成器所在的方法在遍历的时候只会被调用一次,然后后面都只是取数据-偏移的操作

    yield存在的方法被调用 
    0 
    1 
    2 
    3
    4 
最终结论

    如果你需要对一堆数据进行处理,比如把数据从数据库取出然后存储到redis缓存中,可以使用yield这种方式去处理数据,已达到节省内存空间的效果。

    有任何的意见或者错误的地方欢迎指出,虚心接收😝😝😝觉得可以帮到自己的麻烦点个赞👍给点支持鼓励❤❤❤