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

inv*_*sal 60 php memory

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

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

致命错误:第81行的D:\ www\football\views\main.php内存不足(分配786432)(试图分配24576个字节)

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

786432字节只有768千字节,相当小.

提示

  • 错误发生在非常随机的行上.它在第81行并不总是错误.
  • 在高峰时段,Apache只需要大约500mb的内存.我还有6GB备用.
  • 没有无限循环.
  • 该脚本占用1,042,424字节.从中获取此号码echo memory_get_peak_usage();
  • MySQL的结果集很小(最多12行,纯文本,没有blob数据)
  • (重要)如果我每两天重启一次Apache,则错误消失.它通常发生在Apache运行超过2天的时候.
  • 我已经包含了脚本的分析,你可以在这里得到它.
  • 此专用服务器仅用于运行一个网站.该网站是一个高流量的网站,平均每分钟有1,000名访客.在高峰时段,将有1,700到2,000名访客同时访问.

服务器规格

操作系统:Windows 2008 R2 64位
CPU:Intel Core i5 - 4核
RAM:8 GB
Apache 2.2
PHP 5.3.1
存储:2 x 1 TB硬盘
带宽:每月10 TB

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

  1. favicon.ico失踪了我的路线引擎搞砸了.虽然我的路由引擎非常小,但通过包含favicon.ico,它有助于通过不运行我的路由引擎来减少内存使用.我的网站的大部分内容都有它,我忘了把它放在这个新的部分.
  2. 限制有MaxRequestPerChild帮助.在我的其他专用服务器中,我MaxRequestPerChild有限.对于这台服务器,我将其设置为0.我一直认为每个脚本都是隔离的.让我们说如果我的脚本运行800kb.完成后,Apache或PHP应该释放800kb内存.看起来它不会这样工作.有限MaxRequestPerChild确实有助于防止内存泄漏,通过在有限MaxRequestPerChild的旧进程死亡后创建新进程.这是我的新设置.

    ThreadsPerChild      1500
    MaxRequestsPerChild  10000 
    
    Run Code Online (Sandbox Code Playgroud)
  3. ob_flush();确实减少了更多的内存.它没有多大帮助,但每一点优化都有帮助.

  4. xdebug尝试回答这个问题的人建议我使用过以前从未使用过的东西.我不得不说这是一个很好的工具,我已经优化了一些东西,使它运行得更快.
  5. 我已经禁用了一些不必要的Apache模块.我试图逐个禁用它并留下几天测试,以确保它在我禁用另一个之前完美运行.我现在有所有不必要的PHP扩展禁用.
  6. 我在这个服务器中的大多数脚本都使用传统方式(没有模板,没有数据库层,纯PHP,HTML和遗留mysql_*函数).说实话,它运行速度非常快,使用的内存极小.但是,随着网站越来越长,维护脚本并不容易.我试图将网站的某些部分转换为适当的框架(我自己的小框架).之所以我使用自己的框架,因为它很小(整个框架只有3kb,只包括我需要的).
  7. 切换到IIS7.5完全解决了这个问题.

gre*_*reg 27

在尝试使用交换时,我遇到与服务器死亡相同的问题.这是因为mod_php永远不会释放内存.因此,Apache进程不断增长,无论是达到apache还是PHP的内存限制,或者如果没有限制,都会使服务器崩溃.

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

解决方案是在提供一定数量的查询后使apache杀死进程,这样就会创建新的查询(有一些与此相关的问题)将MaxRequestsPerChild配置选项减少到100(默认值为1000).

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

这是我的经历,希望它有所帮助.


Mik*_*osh 15

对于初学者来说,memory_get_peak_usage()这里没有帮助.它只返回分配的内存量,这与导致错误的数量相同.

memory_get_usage 将返回调用时分配的活动内存量.

ini_set('memory_limit', '256M');将在系统内存中设置PHP占用空间的最大容差.如果你在768K获得OOM,那么增加它将无法解决问题.

没有迹象表明您使用的是哪个版本的PHP,但我建议立即进行升级.有几个错误,Zend的内存管理器无法释放内存,这将导致你完全出现同样的问题.

您的本地服务器和生产服务器是否都运行相同版本的操作系统,相同的长位和相同版本的PHP?答案是否定的.

如果它与Windows malloc()问题无关,因为它是一个子域,可能在VirtualHost中,并且仅分配768k,它几乎听起来像操作系统问题.

tasklist访问脚本时从命令提示符运行.您是否看到了额外的Apache线程,或者整个进程中的内存使用率是多少?

最后一个想法是,在表行/列的每个循环之后flush()和/或ob_flush();之后运行.这应该清除缓冲区并在发生问题的情况下为您节省一些内存.


max*_*022 8

我首先将PHP升级到5.4+,因为某些应用程序的速度提高了50%.他们修复了大量的内存泄漏.请参阅becnhamrks:http://news.php.net/php.internals/57760


Luc*_*one 7

请注意,错误是Out of memory和不是Allowed memory size [..] exhausted.

所以内存泄漏在系统的其他地方.在这个繁重的查询之后,mysql服务器可能会使用大量的系统内存,而没有物理和交换的apache/php.

这应该始终在同一行(和/或相同的脚本)中解释错误.


Car*_*don 6

安装xdebug并启用探查器触发器.生成一个探查器文件,然后发布cachegrind文件,如果您仍然无法告诉问题的根源.

编辑:当然发生内存泄漏的页面的探查器文件!


小智 5

致命错误:内存不足(已分配已解决)
我遇到了类似的问题,几个月没有解决方案。最后我检查了 apache 文件夹之一,即(\apache\conf\extra),我遇到了这个控制 apache 内存分配的文件.该文件中的文件名是httpd-mpm,您要增加MaxMemFree,将其设置为2048,以更高的值,我将第一个MaxMemFree(IfModule!mpm_netware_module)的MaxMemFree设置为10000,然后将第二个MaxMemFree设置为5000 IfModule mpm_netware_module。

这些解决了我的问题。希望能帮助到你