账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    PHP可变长参数(...)和生成器问题
    17
    0

    问题来源于 https://segmentfault.com/q/10... 这里。看了@elarity 的回答,他使用了200000的元素插入到redis集合。于是乎我使用了1百万个元素数组来插入,在我这里是内存溢出的,所以我使用了生成器的方式

    function xrange() {
            for ($i=0; $i<1000000; $i++) {
                    yield $i;
            }
    }
    $r = xrange();
    
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    
    $key = 'jimu';
    $redis->del($key);
    $begin = microtime(true);
    $redis->sadd($key, ...$r);
    
    $end = microtime(true);
    echo ($end - $begin) . "\n";

    输出结果:

    [vagrant@localhost ~]$ php redis.php 
    1.2786898612976
    [vagrant@localhost ~]$

    然后redis-cli中确实有了一百万个元素。那么当我把代码中的一百万修改为一千万的时候又报内存溢出

    [vagrant@localhost ~]$ php redis.php 
    PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in /home/vagrant/redis.php on line 6
    
    Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in /home/vagrant/redis.php on line 6

    根据我理解的生成器知识不应该出现内存溢出的情况。因为自始至终生成器xrange只占用一个变量($i)内存?
    所以我猜测是不是$redis->sadd($key, ...$r);这一步的时候...$r依然会解析成大数组。 现在不知道如何证实。


    补充:
    我在sadd之前使用var_dump(...$r);exit;发现输出的都是

    int(999775)
    int(999776)
    int(999777)
    int(999778)
    int(999779)
    int(999780)
    int(999781)

    这样可以证明生成器确实是一个一个产出值的。那么为什么将...$r传入到sadd()的时候还报内存不足呢?不明白这个...的原理,还请大佬们指点。

    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 家盛 普通会员 1楼
      502 Bad Gateway

      502 Bad Gateway


      nginx
    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部