致命错误:内存不足,但我确实有足够的内存 (PHP)

2021-12-21 00:00:00 memory php

由于我的问题越来越长,我决定重新编写整个问题以使其更好更短.

Since my question is getting longer and longer, I decide to re-write the whole question to make it better and shorter.

我在具有 8GB 内存的专用服务器上运行我的网站.我完全知道我需要提高 php.ini 设置的内存限制.我已将其从 128M 设置为 256M 并设置为 -1.问题仍然是持久性.

I run my website on dedicated server with 8GB memory. I am fully aware that I need to raise the memory limit on php.ini setting. I have set it from 128M to 256M and to -1. Still the problem is persistence.

致命错误:内存不足(已分配 786432)(尝试分配 24576字节)在 D:wwwfootballviewsmain.php 中的第 81 行

Fatal error: Out of memory (allocated 786432) (tried to allocate 24576 bytes) in D:wwwfootballviewsmain.php on line 81

内存不足是没有意义的,因为它说只分配了 786432 个字节,而它需要更多的 24576 个字节.

The out of memory does not make sense because it said only 786432 bytes is allocated and it needed 24576 bytes more.

786432 字节仅为 768 KB,相当小.

786432 bytes is only 768 kilobytes and is fairly small.

  • 错误发生在非常随机的行上.它并不总是在第 81 行出错.
  • 在高峰时间,Apache 只占用大约 500MB 的内存.我还有 6GB 可用空间.
  • 没有无限循环.
  • 脚本占用 1,042,424 个字节.从 echo memory_get_peak_usage();
  • 获取这个数字
  • 来自 MySQL 的结果集很小(最多 12 行,纯文本,没有 blob 数据)
  • (重要)如果我每两天重启一次 Apache,错误就会消失.这通常发生在 Apache 运行超过 2 天时.
  • 我已经包含了脚本的分析,您可以在此处获取它.
  • 此专用服务器仅用于运行一个网站.该网站是一个高流量网站,平均每分钟有 1,000 名访问者.在高峰时段,将有 1,700 至 2,000 名访客同时访问.
  • The error occurs on a very random line. It does not always error on line number 81.
  • At peak time, Apache only takes around 500mb of memory. I still have 6GB to spare.
  • There is no infinite loop.
  • The script takes 1,042,424 bytes. Getting this number from echo memory_get_peak_usage();
  • The resultset from MySQL is small (at most 12 of rows, purely text, no blob data)
  • (Important) If I restart Apache once every two days, the error is gone. It usually happens when Apache is running more than 2 days.
  • I have included the profiling the script and you can get it here.
  • This dedicated server is purely used to run only one website. This website is a high traffic website with average of 1,000 visitors every minute. At peak time, there will be 1,700 to 2,000 visitors accessing at the same time.

操作系统:Windows 2008 R2 64 位
CPU:英特尔酷睿 i5 - 4 核
内存:8 GB
Apache 2.2
PHP 5.3.1
存储:2 x 1 TB 硬盘
带宽:每月 10 TB

OS: Windows 2008 R2 64-Bit
CPU: Intel Core i5 - 4 cores
RAM: 8 GB
Apache 2.2
PHP 5.3.1
Storage: 2 x 1 TB hard drives
Bandwidth: 10 TB per month

解决方案

我终于调整并解决了问题,我想在这里分享我所做的改进:

Solution

I have finally tuned up and fixed the problem and I would like to share it here what I have done to improve:

  1. favicon.ico 丢失了,这会影响我的路由引擎.虽然我的路由引擎非常小,但是通过包含 favicon.ico,它可以通过不运行我的路由引擎来帮助减少内存使用.我网站的大部分内容都有它,但我忘了把它放在这个新部分.
  2. Limit MaxRequestPerChild 有帮助.在我的另一个专用服务器中,我的 MaxRequestPerChild 受到限制.对于这个服务器,我设置为0.我一直认为每个脚本都是隔离的.假设我的脚本需要 800kb 才能运行.完成后,Apache 或 PHP 应该释放 800kb 内存.似乎它不能以这种方式工作.受限 MaxRequestPerChild 确实有助于通过在受限 MaxRequestPerChild 和旧进程即将死亡后创建新进程来防止内存泄漏.这是我的新设置.

  1. favicon.ico was missing which mess up with my route engine. Although my route engine is very small, but by including favicon.ico, it helps reduce memory usage by not running my route engine. Most of part of my website has it and I forgot to put it for this new section.
  2. Limit MaxRequestPerChild helps. In my other dedicated server, I have my MaxRequestPerChild limited. For this server, I set it to 0. I always thought that each script is isolated. Lets say if my script takes 800kb to run. Upon its completion, Apache or PHP should free 800kb memory. It seem like it doesn't work this way. Limited MaxRequestPerChild does help to prevent memory leak by creating new process after limited MaxRequestPerChild and the old process is dying. This is my new setting.

ThreadsPerChild      1500
MaxRequestsPerChild  10000 

  • ob_flush(); 确实减少了更多的内存.它没有多大帮助,但每一点优化都有帮助.

  • ob_flush(); does reduce slightly more memory. It does not help much but every bit of optimization helps.

    推荐答案

    我遇到了同样的问题,在尝试使用交换时服务器死机.这是因为mod_php 永远不会释放内存.因此 Apache 进程不断增长,要么达到 apache 或 PHP 的内存限制,要么在没有限制的情况下使服务器崩溃.

    I ran accross the same kind of problem with the server dying when trying to use the swap. This is because mod_php does not free memory ever. So Apache processes keep growing either reaching apache or PHP's memory limit or, if there's no limit, crashing the server.

    重新启动 apache 使其产生新的新的细长进程,但是随着它们运行 PHP 脚本,它们会随着时间的推移而增长,直到出现问题.

    Restarting apache makes it to spawn new fresh slim processes but as they run PHP scripts over time, they grow until problems arise.

    解决方案是让apache在提供一定数量的查询后杀死进程,以便创建新的进程(有与此相关的一些问题) 减少MaxRequestsPerChild 配置选项,假设为 100(默认为 1000).

    The solution is to make apache to kill processes after a certain number of queries served so it will create new ones ( There are some questions related to that) reducing the MaxRequestsPerChild configuration option to, let's say 100 (Defaults to 1000).

    当然,这可能会降低服务器性能,因为它需要资源来终止和生成新进程,但至少它可以保持站点正常工作.您可能想增加正在运行的进程数以保持高性能,确保 PHP(或 apache)内存限制 x 最大进程数不会超过服务器的物理内存.

    Of course this may reduce server performances as it takes ressources to kill and spawn new processes but at least it keeps the site working. You might be tempted to raise the number of running processes to keep performances high, be sure PHP (or apache) memory limit x max number of processes do not get over your server's physical ram.

    以下是我的经验,希望对您有所帮助.

    Here's my experience, hope it helps.

  • 相关文章