跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • PHP 中如何定位内存泄露的代码所在行呢?
未分類
2 9 月 2020

PHP 中如何定位内存泄露的代码所在行呢?

PHP 中如何定位内存泄露的代码所在行呢?

資深大佬 : JJstyle 22

phper 们应该都会自动内存泄露主要由于循环应用导致的,比如如下代码将会导致内存泄露:

function fun1() {   $a = ['hello'];   $a[] = &$a; }  func1(); 

自己的代码还好,可以检查检查,由于使用了第三方依赖,怎么在依赖的文件中定位到有这种有内存泄露的代码呢?小弟实在想不出有什么好的办法

大佬有話說 (18)

  • 資深大佬 : leven87

    memory_get_usage ? 不懂
    知名一些的第三方应用,都有 github 或者论坛吧。

  • 資深大佬 : sagaxu

    循环引用不会导致内存泄露

  • 主 資深大佬 : JJstyle

    @sagaxu 你可以执行我上面的那段代码试试内存使用

  • 資深大佬 : ben1024

    xdebug 监听函数 memory_get_usage(true)/1024/1024/8 的内存值?

  • 資深大佬 : wangritian

    apache/php-fpm/swoole 应该都有一个叫 max_request 的参数,执行一定量请求后重启进程,哪怕代码有内存泄漏也会还给系统

  • 資深大佬 : cholerae

    不懂 php,不过搜了一下看 php 5.3 开始就有能回收环的 gc 了,为啥这个代码会内存泄漏?

  • 主 資深大佬 : JJstyle

    @wangritian 是一段脚本,在 cli 下运行的,其实我只是讨论一个方法,毕竟我可以发现当内存达到一定量时退出,rnhou 让 supervisor 帮我重启

  • 主 資深大佬 : JJstyle

    @JJstyle #7 rnhou => 然后

  • 主 資深大佬 : JJstyle

    @cholerae 我看了一下 php 的文档,大概是 php5.3 后,只有当根缓冲区满了才会 清除循环引用产生的垃圾

  • 資深大佬 : superwhite

    php7.2 win,PHP7.3 centOs,试了你的代码,不会内存泄露

  • 資深大佬 : CismonX

    在 PHP 的 debug build 中,PHP 进程退出时 Zend MM 会打印出未释放的内存的相关信息(仅限那些用 emalloc 系列函数分配的由 Zend MM 管理的内存),包括其地址、分配这块内存的相关函数等

    当然,实际调试的时候这些信息可能不够,需要 valgrind 。

  • 資深大佬 : wangbenjun5

    @wangritian 正解,除非写常驻进程的应用,不然不用操心内存泄露问题,如果要写常驻进程应用,为何不用 go

  • 主 資深大佬 : JJstyle

    @wangbenjun5 帮朋友维护一个个人项目,恰好我对 php 熟悉

  • 資深大佬 : zjsxwc

    看来只能手动 gc 了

    1 <?php
    2
    3
    4 function fun1()
    5 {
    6 $a = [‘hello’];
    7 $a[] = &$a;
    8 }
    9
    10 while(true) {
    11 fun1();
    12 gc_collect_cycles();
    13 echo memory_get_usage() . “n”;
    14 sleep(1);
    15 }

  • 資深大佬 : zjsxwc

    php 碰到内存“泄露”问题,有几个方面
    1. “全局变量” 或者 “常驻依赖注入容器对象” 的膨胀导致内存不够,比如 orm 中 EntityManager 没有及时 clear 追踪的不再被使用的数据库实体对象。
    2. 代码逻辑“死循环” 导致内存不够。
    3. 使用了存在内存泄露 bug 的 c/c++拓展。

    当接上我的回答,当 php 内存达到设置值时,比如 32M 时会自动触发垃圾回收,所以没有必要手动 gc_collect_cycles();

    php 7.3 之后有个 gc_status();可以看 gc 状态

    “`
    [email protected]:~$ cat 2.php
    <?php

    function fun1()
    {
    $a = [‘hello’];
    $a[] = &$a;
    }

    while(true) {
    var_dump(gc_status());
    fun1();
    var_dump(gc_status());
    gc_collect_cycles();
    echo memory_get_usage() . “n”;
    sleep(1);
    }
    [email protected]:~$ ‘/home/zjsxwc/php74/bin/php’ 2.php
    array(4) {
    [“runs”]=>
    int(0)
    [“collected”]=>
    int(0)
    [“threshold”]=>
    int(10001)
    [“roots”]=>
    int(0)
    }
    array(4) {
    [“runs”]=>
    int(0)
    [“collected”]=>
    int(0)
    [“threshold”]=>
    int(10001)
    [“roots”]=>
    int(1)
    }
    365496
    array(4) {
    [“runs”]=>
    int(1)
    [“collected”]=>
    int(1)
    [“threshold”]=>
    int(10001)
    [“roots”]=>
    int(0)
    }
    array(4) {
    [“runs”]=>
    int(1)
    [“collected”]=>
    int(1)
    [“threshold”]=>
    int(10001)
    [“roots”]=>
    int(1)
    }
    365496

    “`

  • 資深大佬 : wangritian

    @wangbenjun5 +1 我也是 web 项目用 php-swoole,小工具或者中间件用 go/python

  • 資深大佬 : gouchaoer2

    php 有检测循环引用的机制,只是内存涨到一定大小才会触发

  • 資深大佬 : jimduan

    php5.3 后的 gc, 已经自动帮我们解决了!
    只需要更多的关注, 业务场景中是否一次性拉取过多的数据进行计算导致 OOM ;常驻内存脚本是否请求了很多资源没有释放

    PHP 的垃圾回收机制-理解 PHP 如何解决循环引用导致的内存泄漏问题
    http://blog.100dos.com/2017/04/07/php-garbage-collection-collect-cycles/

    请手动释放你的资源(Please release resources manually)
    https://www.laruence.com/2012/07/25/2662.html

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具