今天早上刚到公司,有同事反映公司群里某计划任务有问题。怀着一颗求知的心,我去查看了日志。发现一个很有意思的问题,PHP内存溢出导致脚本无法执行。那就一起来一探究竟吧!首先,我检查了计划任务的日志。从错误信息的字面意思可以看出,允许的134217728字节的内存已经用完,尝试分配12961640字节的内存。您已经用完了分配给您的内存(当前脚本),您仍然想向系统请求内存。系统此时要告诉你:楼主家里没有余粮(借用葛优叔叔的一句话)模拟“案发现场”,新建一个mem_exhausted.php文件,复制一个2.4M的日志文件用于测试,并写了一个简单的脚本重现“犯罪现场”,特意分配1M内存读取2.4M日志来执行脚本。“案发现场”重现“事故”原因分析,脚本一次读取大量数据(可能是读取的文件,也可能是读取的数据库)如下图:(logfiledata)intocup(分配给当前脚本的内存),cupcapacity(memory)isnotenough临时解决方案,不是根本原因:ini_set('memory_limit','100M');分批往杯子里倒水(循环,分段读取数据,可以用limit读取数据库)看结果分段读取也能解决问题。其他优化方案应尽量减少静态变量的使用。当需要数据重用时,可以考虑使用引用(&)。数据库操作完成后,应立即关闭连接;一个对象被使用后,要及时调用析构函数(__destruct()),及时销毁使用的变量(unset())。可以使用memory_get_usage()函数根据当前使用的内存来获取当前占用的内存,用于调整程序。unset()函数只有当变量值占用内存空间超过256字节时,才能释放内存空间。(由PHP内核的gc垃圾回收机制决定)直到所有指向该变量的变量(如引用变量)销毁后才会释放内存(PHP变量的底层实现是一个_zval_struct结构,refcount_gc表示referencecountis_ref__gc表示是不是引用)------------------------我是分界线------------------------海阔天空(对Nginx感兴趣的童鞋可以看看)Nginx系列课程索引简介:WebServer与PHP通信姿势熟悉了解Nginx与PHP如何通信互:PHP程序员你应该知道的Nginx知识(上)如何更好的使用Nginx和Nginx配置进阶:PHP程序员应该知道的Nginx(下)深入理解Nginx内核和Nginx运行原理,以及Nginx高性能的秘密解析实战篇:PHP程序猿猴应该知道的Nginx(下)听不如跑。让我们一起开发Nginx的扩展。
