关于Yii2框架跑脚本时内存泄漏问题的分析与解决


Posted in PHP onDecember 01, 2019

现象

在跑 edu_ocr_img 表的归档时,每跑几万个数据,都会报一次内存耗尽

PHP Fatal error:  Allowed memory size of 134217728 bytesexhausted (tried toallocate 135168 bytes)

跟踪代码发现,是在插入时以下代码造成的:

EduOCRTaskBackup::getDb()->createCommand()->batchInsert(EduOCRTaskBackup::tableName(), $fields, $data)->execute();

execute 之后会造成使用内存涨上去,并且在之后 unset 所有变量内存也会有一部分不会删除,直到内存耗尽。

于是跟踪到 Yii2中execute的具体代码块发现在记录 log 的时候会将使用很高的内存,分析代码之后得出造成泄漏的代码块如下:

造成泄漏的代码块

/**
 * Logs a message with the given type and category.
 * If [[traceLevel]] is greater than 0, additional call stack information about
 * the application code will be logged as well.
 * @param string|array $message the message to be logged. This can be a simple string or a more
 * complex data structure that will be handled by a [[Target|log target]].
 * @param integer $level the level of the message. This must be one of the following:
 * `Logger::LEVEL_ERROR`, `Logger::LEVEL_WARNING`, `Logger::LEVEL_INFO`, `Logger::LEVEL_TRACE`,
 * `Logger::LEVEL_PROFILE_BEGIN`, `Logger::LEVEL_PROFILE_END`.
 * @param string $category the category of the message.
 */
public function log($message, $level, $category = 'application')
{
 $time = microtime(true);
 $traces = [];
 if ($this->traceLevel > 0) {
  $count = 0;
  $ts = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
  array_pop($ts); // remove the last trace since it would be the entry script, not very useful
  foreach ($ts as $trace) {
   if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII2_PATH) !== 0) {
    unset($trace['object'], $trace['args']);
    $traces[] = $trace;
    if (++$count >= $this->traceLevel) {
     break;
    }
   }
  }
 }
 
 // 这里是造成内存的罪魁祸首
 $this->messages[] = [$message, $level, $category, $time, $traces];
 if ($this->flushInterval > 0 && count($this->messages) >= $this->flushInterval) {
  $this->flush();
 }
}

造成内存泄漏的原因分析

在 Yii2框架中的 vendor/yiisoft/yii2/log/Logger.php:156 log函数的156行之后会判断 count($this->messages) >= $this->flushInterval

即:内存中存储的 message 的条数要大于等于预设的 $this->flushInterval 才会将内存中的message 刷到磁盘上去。

如果在刷新到磁盘之前就已经将 php.ini 设置的 128M 内存打满的话,会直接报错申请内存耗尽。

很多关于 YII2其他原因的内存泄漏的讨论
https://github.com/yiisoft/yii2/issues/13256

解决方案

在程序开始时,设置 flushInterval 为一个比较小的值

\Yii::getLogger()->flushInterval = 100; // 设置成一个较小的值

在程序执行过程中,每次 execute 之后对内存中的 message 进行 flush

\Yii::getLogger()->flush(true); // 参数传 true 表示每次都会将 message 清理到磁盘中

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
如何使用PHP获取网络上文件
Oct 09 PHP
php判断变量类型常用方法
Apr 24 PHP
smarty 缓存控制前的页面静态化原理
Mar 15 PHP
thinkphp视图模型查询提示ERR: 1146:Table 'db.pr_order_view' doesn't exist的解决方法
Oct 30 PHP
PHP实现腾讯与百度坐标转换
Aug 05 PHP
[原创]PHP实现字节数Byte转换为KB、MB、GB、TB的方法
Aug 31 PHP
Yii2框架数据验证操作实例详解
May 02 PHP
laravel中的一些简单实用功能
Nov 03 PHP
php+ajax实现商品对比功能示例
Apr 13 PHP
PHP批斗大会之缺失的异常详解
Jul 09 PHP
Yii框架 session 数据库存储操作方法示例
Nov 18 PHP
PHP For循环字母A-Z当超过26个字母时输出AA,AB,AC
Feb 16 PHP
详解no input file specified 三种解决方法
Nov 29 #PHP
设定php简写功能的方法
Nov 28 #PHP
如何在centos8自定义目录安装php7.3
Nov 28 #PHP
PHP的new static和new self的区别与使用
Nov 27 #PHP
Laravel 微信小程序后端实现用户登录的示例代码
Nov 26 #PHP
Laravel 微信小程序后端搭建步骤详解
Nov 26 #PHP
php 使用expat方式解析xml文件操作示例
Nov 26 #PHP
You might like
浅谈PHP中其他类型转化为Bool类型
2016/03/28 PHP
php生成条形码的图片的实例详解
2017/09/13 PHP
在JavaScript中获取请求的URL参数[正则]
2010/12/25 Javascript
jQuery下实现等待指定元素加载完毕(可改成纯js版)
2013/07/11 Javascript
jQuery控制的不同方向的滑动(向左、向右滑动等)
2014/07/18 Javascript
node.js中的buffer.fill方法使用说明
2014/12/14 Javascript
DOM基础教程之使用DOM控制表格
2015/01/20 Javascript
基于zepto.js实现仿手机QQ空间的大图查看组件ImageView.js详解
2015/03/05 Javascript
js结合正则实现国内手机号段校验
2015/06/19 Javascript
jQuery实现图片与文字描述左右滑动自动切换的方法
2015/07/27 Javascript
Bootstrap中的Panel和Table全面解析
2016/06/13 Javascript
基于require.js的使用(实例讲解)
2017/09/07 Javascript
Vue.set()动态的新增与修改数据,触发视图更新的方法
2018/09/15 Javascript
原生JS与JQ获取元素的区别详解
2020/02/13 Javascript
django利用request id便于定位及给日志加上request_id
2018/08/26 Python
TensorFlow实现Logistic回归
2018/09/07 Python
Python Django实现layui风格+django分页功能的例子
2019/08/29 Python
python wxpython 实现界面跳转功能
2019/12/17 Python
Tensorflow实现部分参数梯度更新操作
2020/01/23 Python
如何在Python 游戏中模拟引力
2020/03/27 Python
Django实现图片上传功能步骤解析
2020/04/22 Python
Python利用imshow制作自定义渐变填充柱状图(colorbar)
2020/12/10 Python
CSS3 Flexbox中flex-shrink属性的用法示例介绍
2013/12/30 HTML / CSS
Origins悦木之源英国官网:雅诗兰黛集团高端植物护肤品牌
2017/11/06 全球购物
美国酒店控股公司:Choice Hotels
2018/06/15 全球购物
拥有超过850家商店的美国在线派对商店:Party City
2018/10/21 全球购物
意大利辅助药品、药物和补品在线销售:FarmaEurope
2020/04/29 全球购物
质检部经理岗位职责
2014/02/19 职场文书
婚庆司仪主持词
2014/03/15 职场文书
太太口服液广告词
2014/03/20 职场文书
公司寄语大全
2014/04/10 职场文书
2015入党自荐书范文
2015/03/05 职场文书
2015年推普周活动总结
2015/03/27 职场文书
学术会议通知范文
2015/04/15 职场文书
最新的离婚协议书范本!
2019/07/02 职场文书
各类场合主持词开场白范文集锦
2019/08/16 职场文书