致命错误:内存不足,但我有足够的内存(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
解
我终于调整并解决了这个问题,我想在这里分享我所做的改进:
-
favicon.ico
是缺less哪个搞乱我的路线引擎。 虽然我的路由引擎非常小,但通过包括favicon.ico
,它可以通过不运行我的路由引擎来帮助减less内存使用。 我的网站大部分都有它,我忘了把它放在这个新的部分。 -
限制
MaxRequestPerChild
帮助。 在我的其他专用服务器,我有我的MaxRequestPerChild
有限。 对于这个服务器,我把它设置为0.我一直认为每个脚本都是孤立的。 可以说,如果我的脚本需要800kb运行。 完成后,Apache或PHP应该释放800kb内存。 看起来这样不行。 有限的MaxRequestPerChild
通过在有限的MaxRequestPerChild
和旧的进程正在死亡之后创build新的进程来帮助防止内存泄漏。 这是我的新设置。ThreadsPerChild 1500 MaxRequestsPerChild 10000
-
ob_flush();
确实减less了更多的内存。 它没有多大的帮助,但每一个优化的帮助。 - 我曾经使用过以前从未用过的
xdebug
,正如试图回答这个问题的人所build议的那样。 我不得不说这是一个很好的工具,我已经优化了一些东西,使其运行速度稍快。 - 我已经禁用了一些不必要的Apache模块。 我试图逐个禁用它,并且在禁用另一个之前testing它以确保它完美地工作。 我现在有所有不必要的PHP扩展禁用。
- 这个服务器中的大部分脚本都使用传统的方式(没有模板,没有数据库层,纯PHP,HTML和传统的mysql_ *函数)。 说实话,它运行速度非常快,并使用非常小的内存。 但是,维护脚本并不容易,因为网站越来越长。 我试图将网站的一些部分转换成适当的框架(我自己的小框架)。 之所以使用我自己的框架,是因为它很小(整个框架只有3kb,只包含我需要的)。
- 切换到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。
以下两个事实明确指出内存泄漏:
- 错误出现在代码的不同行中,
- 该错误报告相对较小的内存分配。
我首先会selectPDO,禁用所有其他的扩展,并让它使用Siege / Apache Bench(ab)之类的东西来运行。 你也可以尝试使用cli
界面来运行它(只要确保你保持相同的内存限制)。
您可以在脚本末尾使用memory_get_peak_usage()
函数来查看PHP认为它已经使用了多less内存。
从你的评论是800 kB,这是可以的; 绝对不是会导致内存不足的巨大内存量;-)
最后,虽然我现在不推荐升级到5.4,但由于5.3.1以来已经解决了多个漏洞和漏洞,升级到最新的5.3.x可能是值得的
这发生在我前几天。 我做了一个新的安装,它仍然发生。 只要每个人都看到并根据您的服务器规格。 最有可能是一个无限循环。 它可能不在PHP代码本身,而是在对Apache的请求。
可以说当你访问这个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的可扩展性,所以这是我唯一可能的原因。