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

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

我在8GB内存的专用服务器上运行我的网站。 我完全知道,我需要提高php.ini设置的内存限制。 我已经把它从128M设置为256M和-1。 问题仍然存在。

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

内存不足没有意义,因为它表示只分配了786432个字节,并且需要更多的24576个字节。

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

提示

  • 错误发生在一个非常随机的线上。 第81行不总是出错。
  • 在高峰期,Apache只需要大约500MB的内存。 我还有6GB的空间。
  • 没有无限循环。
  • 该脚本需要1,042,424字节。 从echo memory_get_peak_usage();获取这个数字echo memory_get_peak_usage();
  • MySQL的结果集很小(最多12行,纯文本,没有斑点数据)
  • 重要 )如果我每两天重新启动Apache一次,错误消失了。 当Apache运行超过2天时,通常会发生这种情况。
  • 我已经包括了分析脚本,你可以在这里得到它。
  • 这个专用服务器纯粹只用于运行一个网站。 这个网站是一个高stream量的网站,平均每分钟有1000个访问者。 在高峰时间,将有1700到2000名访问者同时访问。

服务器规格

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

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

  1. favicon.ico是缺less哪个搞乱我的路线引擎。 虽然我的路由引擎非常小,但通过包括favicon.ico ,它可以通过不运行我的路由引擎来帮助减less内存使用。 我的网站大部分都有它,我忘了把它放在这个新的部分。
  2. 限制MaxRequestPerChild帮助。 在我的其他专用服务器,我有我的MaxRequestPerChild有限。 对于这个服务器,我把它设置为0.我一直认为每个脚本都是孤立的。 可以说,如果我的脚本需要800kb运行。 完成后,Apache或PHP应该释放800kb内存。 看起来这样不行。 有限的MaxRequestPerChild通过在有限的MaxRequestPerChild和旧的进程正在死亡之后创build新的进程来帮助防止内存泄漏。 这是我的新设置。

     ThreadsPerChild 1500 MaxRequestsPerChild 10000 
  3. ob_flush(); 确实减less了更多的内存。 它没有多大的帮助,但每一个优化的帮助。

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

在尝试使用交换时,我遇到了与服务器死机相同types的问题。 这是因为mod_php并没有释放内存 。 所以Apache进程不断增长,要么达到Apache或PHP的内存限制,要么没有限制,会导致服务器崩溃。

重新启动apache使得它产生新的苗条进程,但随着时间的推移PHP脚本,他们成长,直到问题出现。

解决的办法是让apache在一定数量的查询服务之后终止进程,因此它会创build新的(有一些相关的问题 ),将MaxRequestsPerChildconfiguration选项减less到100(默认为1000)。

当然这可能会降低服务器的性能,因为它需要资源来杀死和产生新的进程,但至less可以保持网站的正常运行。 你可能会试图提高正在运行的进程的数量,以保持高性能,确保PHP(或apache)内存限制x最大进程数不会超过你的服务器的物理内存。

这是我的经验,希望它有帮助。

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

memory_get_usage将返callback用时正在分配的活动内存量。

ini_set('memory_limit', '256M'); 将设置您的系统内存上的PHP的足迹的最大限额。 如果你在768K获得OOM,那么它将不能解决问题。

没有迹象表明你正在使用哪个版本的PHP,但我会build议立即升级。 Zend的内存pipe理器无法解除分配内存,这会导致你完全相同的问题。

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

如果它与Windows的malloc()问题无关,因为它是一个子域,可能在一个虚拟主机,并分配只有768K,它几乎听起来像一个操作系统的问题。

访问脚本时,从命令提示符运行tasklist 。 你看到一个额外的Apache线程,或整个进程穗内存使用情况?

最后一个想法是,运行flush()和/或ob_flush(); 在表格行/列的每个循环之后。 这应该清除你的缓冲区,并在事件发生的地方为你节省一些内存。

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

安装xdebug并启用分析器触发器。 生成一个profiler文件,然后张贴cachegrind文件,如果你仍然不能告诉问题的根源。

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

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

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

这应该解释错误总是在同一行(和/或在同一个脚本)。

我猜想你要么没有编辑正确的php.ini要么你没有重新启动PHP和/或Web服务器。

在你的文档根目录下创build一个phpinfo.php页面,内容为<?php phpinfo(); 确保你正在改变正确的php.ini 。 除了web服务器正在使用的php.ini文件的位置外,它还将声明允许的最大脚本内存。

接下来,我会添加一些堆栈跟踪到你的页面,所以你可以看到导致这一连串的事件。 以下函数将捕获致命错误,并提供有关所发生事件的更多信息。

 register_shutdown_function(function() { if($error = error_get_last()) { // Should actually log this instead of printing out... var_dump($error); var_dump(debug_backtrace()); } }); 

就我个人而言,Nginx + PHP-FPM是我离开缓慢的Apache以来多年使用的。

嘿,我也有我的服务器上的相同的问题。 我只是改变了以下几点:

php.ini更改为…

 memory_limit = 128M 

并添加到httpd.conf

 RLimitMEM 1073741824 2147483648 

并重新启动Apache&我删除了错误:

可能是MySQL的问题以及打开的连接数量,因此为什么每隔几天重新启动一次就自行排列。 他们自动closures脚本closures?

回顾一下(我将这个答案与原始问题的距离相当远):

  • PHP无法分配似乎是less量的内存
  • 错误发生时的当前内存使用量+所请求的数量小于当前生效的内存限制
  • 当发生这种情况时,系统有6Gb可供PHP使用
  • 因为问题是通过重新启动apache解决的 – 它是防止内存从PHP可用的apache

如果这些都是有效的,那么唯一可能的解释是6Gb是非常分散的 – 我认为这是不太可能的。 你没有说如何从Apache调用PHP – mod_php? FPM? FCGI?

我将首先考察上述每个谓词 – 特别是自由记忆。 你怎么知道发生错误时有6Gb的空闲空间? 更可能的原因是有一个内存泄漏发生,你没有发现。

你还没有提供如何configurationApache的任何细节; 我也看看减lessMaxRequestsPerChild和MaxMemFree。 (我不熟悉工作的Apache每个线程将适用于这 – 每个进程真的需要一个限制)。 如果你从apacheconfiguration提供核心设置,那么也许我们可以提出进一步的build议。

除非广泛使用Ajax,否则确保您的Keepalive时间是2或更less。

以下两个事实明确指出内存泄漏:

  1. 错误出现在代码的不同行中,
  2. 该错误报告相对较小的内存分配。

我首先会selectPDO,禁用所有其他的扩展,并让它使用Siege / Apache Bench(ab)之类的东西来运行。 你也可以尝试使用cli界面来运行它(只要确保你保持相同的内存限制)。

您可以在脚本末尾使用memory_get_peak_usage()函数来查看PHP认为它已经使用了多less内存。

从你的评论是800 kB,这是可以的; 绝对不是会导致内存不足的巨大内存量;-)

最后,虽然我现在不推荐升级到5.4,但由于5.3.1以来已经解决了多个漏洞和漏洞,升级​​到最新的5.3.x可能是值得的

这发生在我前几天。 我做了一个新的安装,它仍然发生。 只要每个人都看到并根据您的服务器规格。 最有可能是一个无限循环。 它可能不在PHP代码本身,而是在对Apa​​che的请求。

可以说当你访问这个urlhttp:// localhost / mysite / page_with_multiple_requests

检查你的Apache的访问日志,如果它收到多个请求。 跟踪请求并检查可能导致系统“瓶颈”的代码(使用sendmail时,我的exec())。 我所说的瓶颈不一定是一个“无限循环”。 这可能是需要一段时间才能完成的function。 或者可能是一些PHP的“ 程序执行function ”

您可能也需要检查ajax请求(在页面加载时执行的请求)。 如果该Ajax请求redirect到相同的url

例如httpx:// localhost / mysite / page_with_multiple_requests

它会再次“重做”这些请求

这将有助于如果您发布随机行或脚本结束的代码本身可能有一个“循环”代码的地方。 恕我直言PHP不会只是随便的线路罢了。

http://blog.piratelufi.com/2012/08/browser-sending-multiple-requests-at-once/

大多数情况下,你会得到这样的错误,问题在代码中。 我并不是想说你正在编写不好的代码,我想说的是,你需要仔细观察那里正在使用这么多的内存。

永远记得“ PHP中的垃圾收集非常糟糕 ”,它不像Java,任何其他这样的语言。 有一种方法可以通过gc_collect_cycle强制垃圾收集,但是我个人认为这并不能解决你的问题。 PHP释放所有用于执行页面的内存,一旦请求 – 响应周期完成,所以如果你的脚本长时间运行,就像后台脚本(Gearman等)一样,你可能会遇到内存问题,因为内存不能释放脚本正在运行。

如果你的scr,pt不是这种情况,而且正如你所说的那样,没有代码需要如此巨大的内存,那么问题肯定是代码本身,升级到任何版本的PHP都不会解决问题。 我曾经面对过我的一个Gearman脚本,并且在我的一个循环中出现了一个问题,那就是我将一个variables追加到我的一个数组中,variables本身非常重(大约110KB的数据)。 所以我build议,仔细检查你的代码。

强夺

我有一个与PHP类似的问题:

1)检查你的错误日志。 在继续之前消除每一个错误。 2)考虑修改你的apacheconfiguration,以消除未使用的模块 – 这将减lessPHP所需的足迹 – 这是一个伟大的链接 – 这是特定于Wordpress,但应该仍然是非常有用的http://thethemefoundry.com/blog/optimize- Apache的WordPress的/

为了让你知道我发现的错误,我有一些代码试图将内容发布到Facebook,Facebook然后修改它们的API,所以这个破坏,我也使用了一个“内容expirator”,这基本上意味着它不断重试将这些内容发布到Facebook并留下内存中的负载。

从分析器输出文件中,我注意到了一些我不太喜欢/信任的东西,并会考虑这些:

除了不知道输出数字的含义来检测exception或PHP脚本如何工作,这是不是一个问题? 有一个包含相同的main.ph文件,看起来像recursion的东西?

 2121 fl=D:\www\football\views\main.php 2122 fn=include::D:\www\football\views\main.php 

注意到文件D:\www\football\views\main.php正在多次使用一些string函数,我想这是对你的查询返回的数据调用这些函数:

 strlen substr strtotime 

如果像在C语言中一样,这些函数需要string为null终止或string终止符的一些其他结尾,以避免内存问题,我会查看您的查询返回的string。

你可以发布你的网站的url?

这是PHP v 5.2 for Windows中的一个已知错误,至less在5.2.3版本中是这样的: https : //bugs.php.net/bug.php? id =41615

没有build议的修复对我们有帮助,我们将不得不更新PHP。

尝试通过fcgid运行php,这可能有所帮助:

这些是将PHP作为Apache模块运行时会遇到的经典错误。 几个月来我们一直在努力解决这些错误。 切换到使用PHP通过mod_fcgid(如詹姆斯build议)将解决所有这些问题。 确保安装了最新的Visual C ++可再发行组件包:

http://support.microsoft.com/kb/2019667

另外,我build议切换到64位版本的MySQL。 没有真正的理由再运行32位版本。

来源: 由于php5ts.dll 5.5.1.0中的问题,Apache 2.4.6.0崩溃

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

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

我会说服务器物理/交换内存不足,所以PHP不能分配足够的内存。

你可以在这里粘贴free的输出吗?

对于我的情况,这个错误是由于一个巨大的select查询(成千上万的返回结果)触发的。

它在我的数据库中添加了数百万条logging后立即产生,以testingWordPress的可扩展性,所以这是我唯一可能的原因。