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

现象

在跑 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 清理到磁盘中

总结

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

(0)

相关推荐

  • 从零开始学YII2框架(二)通过 Composer 安装扩展插件

    目前yii2的扩展还不是很多,截止到今天,在官网一共有33个,不过这些插件中不乏有优秀的扩展插件, 我尝试了几个,发现了一系列好用的Yii2插件,作者是来自印度的krajee团队,他们写的插件都很好用.推荐一下. krajee团队的网站:http://krajee.com,有几个不错的插件可以尝试. 下面来介绍Yii2的插件安装方法.通过Composer安装插件yii2-detail-view. Git 推荐安装Git,Composer安装插件时候会用到Git Clone,Git官方下载网站:传

  • 从零开始学YII2框架(三)扩展插件yii2-gird

    yii2-gird 插件是Yii2.0的一个扩展.它在官方的girdview基础上扩展了一些实用的功能. 比如: 把表格包装在bootstrap - panel标签下,使之更美观: Float Header功能,实现滑动表格的时候,表字段至于屏幕上方,方便查看: 新增操作栏说明label: 页面统计功能: 新增重置表格功能: 新增导出表格功能,包括四种常用格式[html.CSV.txt.Excel]. 非常感谢Kartik团队带来的好用的插件.Kartik团队的其他插件也很好用的.推荐试用. 安

  • 从零开始学YII2框架(四)扩展插件yii2-kartikgii

    今天发现了一款好用的插件yii2-kartikgii.它是基于系列插件kartik-v的拓展. 插件介绍 这个插件主要功能是帮助你在使用gii生成代码curd的时候生成kartik-gird的.不需要每次用默认的gii工具生成代码之后再手动添加kartik-gird,这正是我想要的功能.快速生成kartik-grid. 学习这个插件之前你可能需要了解下yii2-gird插件:传送门 插件安装与配置 直接看插件网址: http://www.yiiframework.com/extension/yi

  • Yii2框架使用计划任务的方法

    本文实例讲述了Yii2框架使用计划任务的方法.分享给大家供大家参考,具体如下: <?php namespace console\controllers; use yii\console\Controller; /** * Test controller */ class TestController extends Controller { public function actionIndex() { echo "cron service runnning"; } public

  • 从零开始学YII2框架(六)高级应用程序模板

    高级应用程序模板 这个模板用在大型的团队开发项目中,而且后台从前台独立分离出来以便于部署在多个服务器中.由于YIi2.0的一些新的特性,这个程序模板的功能要更深一点.提供了基本的数据库的支持,注册.密码找回等功能. 安装 可以通过Composer来安装 如果没有安装Composer,先安装 curl -s http://getcomposer.org/installer | php 然后用如下命令来获取 php composer.phar create-project --prefer-dist

  • 从零开始学YII2框架(五)快速生成代码工具 Gii 的使用

    Yii2 框架 之所以称之为高效快速开发的一款框架,是因为有一个神奇的工具Gii 用过Yii1框架的Coder都知道,Gii可以为你快速生成代码,也就是说搭建一个可以增删改查的WebApp可能一行代码都不用写. 当然作为Coder,不写代码怎么能实现我们想要的功能呢. 上次介绍了如何安装Yii框架,本次介绍一下如何使用gii工具快速实现CRUD功能. 框架安装完成后可以通过如下链接访问Gii工具 http://localhost/yii2test/backend/web/index.php?r=

  • Yii2框架数据库简单的增删改查语法小结

    User::find()->all(); //返回所有用户数据: User::findOne($id); //返回 主键 id=1 的一条数据: User::find()->where(['name' => 'ttt'])->one(); //返回 ['name' => 'ttt'] 的一条数据: User::find()->where(['name' => 'ttt'])->all(); //返回 ['name' => 'ttt'] 的所有数据: U

  • 从零开始学YII2框架(一)通过Composer安装Yii2框架

    最近在学习PHP,着手找一个能快速上手的框架来学习.一开始看兄弟连视频时候讲师推荐ThinkPHP.于是我选择了ThinkPHP来尝试,这个框架的上手难度系数不大,能快速开发一款应用.适合小型的企业应用.因为是国人开发的,中文支持比较好.有比较全面的文档,官网社区也比较活跃.因为我接触的项目都是用Oracle数据库的,所以我想找一款对Oracle支持比较好的PHP框架,但是ThinkPHP框架对Oracle的支持实在是不好.所以我换了Yii框架来试试对Oracle的支持程度. Yii框架现在稳定

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

    现象 在跑 edu_ocr_img 表的归档时,每跑几万个数据,都会报一次内存耗尽 PHP Fatal error:  Allowed memory size of 134217728 bytesexhausted (tried toallocate 135168 bytes) 跟踪代码发现,是在插入时以下代码造成的: EduOCRTaskBackup::getDb()->createCommand()->batchInsert(EduOCRTaskBackup::tableName(), $

  • 基于Keras 循环训练模型跑数据时内存泄漏的解决方式

    在使用完模型之后,添加这两行代码即可清空之前model占用的内存: import tensorflow as tf from keras import backend as K K.clear_session() tf.reset_default_graph() 补充知识:keras 多个模型测试阶段速度越来越慢问题的解决方法 问题描述 在实际应用或比赛中,经常会用到交叉验证(10倍或5倍)来提高泛化能力,这样在预测时需要加载多个模型.常用的方法为 mods = [] from keras.ut

  • Spring关闭Tomcat Servlet容器时内存泄漏问题解决方案

    这篇文章主要介绍了Spring关闭Tomcat Servlet容器时内存泄漏问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 出错信息 22-Sep-2017 06:19:51.064 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears t

  • 导致MyEclipse内存不足的原因分析及解决办法

    1.修改eclipse.ini 在Myeclipse安装目录下G:\MyEclipse8.5\Genuitec\MyEclipse 8.5有一个myeclipse.ini配置文件,设置如下: -vmargs -Xmx512m -XX:MaxPermSize=256m -XX:ReservedCodeCacheSize=64m 2.设置Default VM Arguments 在myEclipse中,打开Windows-> Preferences->Java->Installed JREs

  • Yii2框架配置文件(Application属性)与调试技巧实例分析

    本文实例讲述了Yii2框架配置文件(Application属性)与调试技巧.分享给大家供大家参考,具体如下: 配置文件 Yii2的主要配置文件config\web.php: <?php $params = require(__DIR__ . '/params.php'); $config = [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'bootstrap' => ['log'], 'components' => [

  • C++中关于Crt的内存泄漏检测的分析介绍

    尽管这个概念已经让人说滥了 ,还是想简单记录一下, 以备以后查询. 复制代码 代码如下: #ifdef _DEBUG#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)#else#define DEBUG_CLIENTBLOCK#endif#define _CRTDBG_MAP_ALLOC#include <crtdbg.h>#ifdef _DEBUG#define new DEBUG_CLIENTBLOCK#e

  • Android性能优化之利用强大的LeakCanary检测内存泄漏及解决办法

    前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来.所以决定抽空学习总结一下这方面的知识,以及分享一下我们是如何检测内存泄漏的.我们公司使用开源框架LeakCanary来检测内存泄漏. 什么是内存泄漏? 有些对象只有有限的生命周期.当它们的任务完成之后,它们将被垃圾回收.如果在对象的生命周期本该结束的时候,这个对象还被一系列的引用,这就会导致内存泄漏

  • Erlang项目内存泄漏分析方法

    随着项目越来越依赖Erlang,碰到的问题也随之增加.前段时间线上系统碰到内存高消耗问题,记录一下troubleshooting的分析过程.线上系统用的是Erlang R16B02版本. 问题描述 有几台线上系统,运行一段时间,内存飙升.系统模型很简单,有网络连接,pool中找新的process进行处理.top命令观察,发现内存都被Erlang进程给吃完了,netstat命令查看网络连接数,才区区几K.问题应该是Erlang内存泄漏了. 分析方法 Erlang系统有个好处,可以直接进入线上系统,

  • 5个Android开发中比较常见的内存泄漏问题及解决办法

    android中一个对象已经不需要了,但是其他对象还持有他的引用,导致他不能回收,导致这个对象暂存在内存中,这样内存泄漏就出现了. 内存泄漏出现多了,会是应用占用过多的没存,当占用的内存超过了系统分配的内存容量,就会出现内存溢出了导致应用Crash. 了解了内存泄漏的原因及影响后,我们需要做的就是掌握常见的内存泄漏,并在以后的Android程序开发中,尽量避免它.下面搜罗了5个Android开发中比较常见的内存泄漏问题及解决办法,分享给大家,一起来看看吧. 一.单例造成的内存泄漏 android

  • Android Studio 3.0上分析内存泄漏的原因

    以前用eclipse的时候,我们采用的是DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来比较麻烦.后来随着Android studio的潮流,我也抛弃了eclipse加入了AS. Android Studio也开始支持自动进行内存泄漏检查,并且操作起来也比较方便. 封面 戳我下载 Android Studio 3.0 这个不用梯子我会告诉你吗 1.写在前面 Google在上周发布了Android Studio 3.0的正式版本,周四早晨在上班的地铁上就看到群里在沸沸

随机推荐