致命错误:内存不足,但我确实有足够的内存 (PHP)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12015569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fatal error: Out of memory, but I do have plenty of memory (PHP)
提问by invisal
Since my question is getting longer and longer, I decide to re-write the whole question to make it better and shorter.
由于我的问题越来越长,我决定重新编写整个问题以使其更好更短。
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.
我在具有 8GB 内存的专用服务器上运行我的网站。我完全知道我需要提高 php.ini 设置的内存限制。我已将其从 128M 设置为 256M 并设置为 -1。问题仍然是持久性。
Fatal error: Out of memory (allocated 786432) (tried to allocate 24576 bytes) in D:\www\football\views\main.php on line 81
致命错误:第 81 行 D:\www\football\views\main.php 中的内存不足(已分配 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 个字节,并且还需要 24576 个字节。
786432 bytes is only 768 kilobytes and is fairly small.
786432 字节只有 768 KB 并且相当小。
Hints
提示
- 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.
- 错误发生在非常随机的行上。它并不总是在第 81 行出错。
- 在高峰时间,Apache 只需要大约 500mb 的内存。我还有 6GB 可用空间。
- 没有无限循环。
- 该脚本占用 1,042,424 个字节。从
echo memory_get_peak_usage(); - MySQL 的结果集很小(最多 12 行,纯文本,无 blob 数据)
- (重要)如果我每两天重新启动一次 Apache,错误就会消失。它通常发生在 Apache 运行超过 2 天时。
- 我已经包括了脚本的分析,你可以在这里得到它。
- 此专用服务器仅用于运行一个网站。该网站是一个高流量网站,平均每分钟有 1,000 名访问者。高峰时段,将有1,700至2,000名访客同时进入。
Server Spec
服务器规格
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
操作系统: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
Solution
解决方案
I have finally tuned up and fixed the problem and I would like to share it here what I have done to improve:
我终于调整并解决了问题,我想在这里分享我为改进所做的工作:
favicon.icowas missing which mess up with my route engine. Although my route engine is very small, but by includingfavicon.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.Limit
MaxRequestPerChildhelps. In my other dedicated server, I have myMaxRequestPerChildlimited. 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. LimitedMaxRequestPerChilddoes help to prevent memory leak by creating new process after limitedMaxRequestPerChildand the old process is dying. This is my new setting.ThreadsPerChild 1500 MaxRequestsPerChild 10000ob_flush();does reduce slightly more memory. It does not help much but every bit of optimization helps.- I have used
xdebugwhich I have never used before as suggested by people who attempt to answer this question. I have to say it is great tool and I have optimized a few stuffs to make it run slightly faster. - I have disable a few unnecessary Apache module. I am trying to disable it one by one and leave it a few days test to ensure it works perfectly before I disable another one. I do have all unnecessary PHP extension disable now.
- Most of my script in this server used traditional way (no template, no database layer, pure PHP, HTML, and legacy mysql_* function). To be honest, it runs very fast and used extremely small memory. However, maintenance the script is not very easy as the website is getting longer. I have tried to convert some parts of the website into proper framework (my own tiny framework). The reason that I used my own framework because it is tiny (3kb for the whole framework and include only what I need).
- Switching to IIS7.5 solving this problem completely.
favicon.ico丢失了,这弄乱了我的路线引擎。虽然我的路由引擎非常小,但通过包含favicon.ico,它有助于通过不运行我的路由引擎来减少内存使用。我网站的大部分内容都有它,但我忘了把它放在这个新部分。限制有
MaxRequestPerChild帮助。在我的另一个专用服务器中,我有我的MaxRequestPerChild限制。对于这个服务器,我设置为0。我一直认为每个脚本都是隔离的。假设我的脚本需要 800kb 才能运行。完成后,Apache 或 PHP 应该释放 800kb 内存。似乎它不能以这种方式工作。Limited 通过MaxRequestPerChild在LimitedMaxRequestPerChild和旧进程死亡后创建新进程来帮助防止内存泄漏。这是我的新设置。ThreadsPerChild 1500 MaxRequestsPerChild 10000ob_flush();确实减少了更多的内存。它没有多大帮助,但每一点优化都有帮助。xdebug正如试图回答这个问题的人所建议的那样,我使用了我以前从未使用过的东西。我不得不说这是一个很棒的工具,我优化了一些东西,让它运行得稍微快一点。- 我禁用了一些不必要的 Apache 模块。我正在尝试一个一个地禁用它,并在我禁用另一个之前对其进行几天测试以确保它可以正常工作。我现在确实禁用了所有不必要的 PHP 扩展。
- 我在这个服务器上的大部分脚本都使用传统方式(没有模板,没有数据库层,纯 PHP、HTML 和遗留的 mysql_* 函数)。老实说,它运行得非常快,而且使用的内存非常小。然而,随着网站越来越长,维护脚本并不是很容易。我试图将网站的某些部分转换为适当的框架(我自己的小框架)。我使用自己的框架的原因是它很小(整个框架为 3kb,仅包含我需要的内容)。
- 切换到IIS7.5完全解决这个问题。
回答by greg
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.
我在尝试使用交换时遇到了服务器死机的相同问题。这是因为mod_php 永远不会释放内存。因此 Apache 进程不断增长,要么达到 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 使其产生新的新的细长进程,但是随着它们随着时间的推移运行 PHP 脚本,它们会不断增长,直到出现问题。
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 MaxRequestsPerChildconfiguration option to, let's say 100 (Defaults to 1000).
解决方案是让 apache 在提供一定数量的查询后终止进程,以便创建新的进程(有一些与此相关的问题)将MaxRequestsPerChild配置选项减少到 100(默认为 1000)。
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.
当然,这可能会降低服务器性能,因为它需要资源来终止和生成新进程,但至少它可以保持站点正常工作。您可能想增加正在运行的进程数以保持高性能,请确保 PHP(或 apache)内存限制 x 最大进程数不会超过服务器的物理内存。
Here's my experience, hope it helps.
以上是我的经验,希望有帮助。
回答by Mike Mackintosh
For starters, memory_get_peak_usage()will not be helpful here. It will only return the amount of memory which was allocated, and that is the same number which caused the error.
对于初学者来说,memory_get_peak_usage()这里不会有帮助。它只会返回分配的内存量,这与导致错误的数字相同。
memory_get_usagewill return the active amount of memory which is being allocated when it is called.
memory_get_usage将返回调用时正在分配的活动内存量。
ini_set('memory_limit', '256M');will set the maximum allowance of PHP's footprint on your systems Memory. If you are getting OOM at 768K, upping it will not fix the problem.
ini_set('memory_limit', '256M');将设置 PHP 在您的系统内存上占用的最大允许量。如果您在 768K 时出现 OOM,则提高它不会解决问题。
There is no indication as to what version of PHP you are using, but I would suggest an upgrade immediately. There are several bugs where Zend's Memory Manager fails to deallocate memory, which would lead you exactly to the same problem.
没有迹象表明您使用的是哪个版本的 PHP,但我建议您立即升级。Zend 的内存管理器无法释放内存有几个错误,这将导致您完全相同的问题。
Are both your local server and your production server running the same version of OS, the same long bit and the same version of PHP? The answer will be no.
您的本地服务器和生产服务器是否运行相同版本的操作系统、相同的长位和相同版本的 PHP?答案是否定的。
If it is unrelated to the windows malloc()issue, being it is a sub domain and probably within a VirtualHost, and allocating only 768k, it almost sounds like an OS issue.
如果它与 Windowsmalloc()问题无关,因为它是一个子域并且可能在 VirtualHost 内,并且只分配 768k,这听起来几乎像是一个操作系统问题。
Run tasklistfrom the command prompt when you access your script. Do you see an additional Apache thread, or Memory usage across the processes spike?
tasklist访问脚本时从命令提示符运行。您是否看到了额外的 Apache 线程,或跨进程的内存使用量激增?
One last idea is, run flush()and/or ob_flush();after each loop for the table row/column. This should clear your buffer and save you some memory in the event this is where the issue is occurring.
最后一个想法是,在表格行/列的每个循环之后运行flush()和/或ob_flush();之后。这应该会清除您的缓冲区并在发生问题时为您节省一些内存。
回答by maxwell2022
I would start by upgrading PHP to 5.4+ as it's up to 50% faster for some applications. They fixed a large number of memory leaks. Please see becnhamrks: http://news.php.net/php.internals/57760
我首先将 PHP 升级到 5.4+,因为对于某些应用程序,它的速度最多可提高 50%。他们修复了大量内存泄漏。请参阅becnhamrks:http://news.php.net/php.internals/57760
回答by Luca Rainone
Please note that the error is Out of memoryand is not Allowed memory size [..] exhausted.
请注意,错误是Out of memory和不是Allowed memory size [..] exhausted。
So the memory leak is elsewhere on the system. It's possible that mysql server use a lot of system memory after this heavy query, leaving apache/php without it physical and swap.
所以内存泄漏发生在系统的其他地方。在这个繁重的查询之后,mysql 服务器可能会使用大量的系统内存,让 apache/php 没有物理和交换。
This should explain the error always on the same line (and/or in the same script).
这应该总是在同一行(和/或在同一脚本中)解释错误。
回答by Carmageddon
Install xdebug and enable profiler trigger. Generate a profiler file, then post the cachegrind file if you still would not be able to tell the source of the problem.
安装 xdebug 并启用分析器触发器。生成一个分析器文件,如果您仍然无法说出问题的根源,则发布 cachegrind 文件。
EDIT: profiler file of the page where the memory leak happens of course!
编辑:当然发生内存泄漏的页面的分析器文件!
回答by Xeoncross
I would guess that you either haven't edited the right php.inior you haven't restarted PHP and/or the webserver.
我猜你要么没有编辑权限,php.ini要么没有重新启动 PHP 和/或网络服务器。
Create a phpinfo.phppage in your docroot with the contents <?php phpinfo();to make sure you are changing the correct php.ini. In addition to the location of the php.inifile the webserver is using, it will also state the maximum script memory allowed.
phpinfo.php在您的 docroot 中创建一个包含内容的页面,<?php phpinfo();以确保您更改了正确的php.ini. 除了php.ini网络服务器正在使用的文件的位置之外,它还将说明允许的最大脚本内存。
Next, I would add some stack traces to your page so you can see the chain of events that led to this. The following function will catch fatal errors and provide more information about what happened.
接下来,我将向您的页面添加一些堆栈跟踪,以便您可以查看导致此问题的事件链。以下函数将捕获致命错误并提供有关所发生情况的更多信息。
register_shutdown_function(function()
{
if($error = error_get_last())
{
// Should actually log this instead of printing out...
var_dump($error);
var_dump(debug_backtrace());
}
});
Personally, Nginx + PHP-FPM is what I have used for years since I left slow ol' Apache.
就个人而言,Nginx + PHP-FPM 是我离开缓慢的 Apache 多年以来一直使用的东西。
回答by Rohitashv Singhal
Hey I also got the same problem on my server. I just changed the following things :
嘿,我在我的服务器上也遇到了同样的问题。我只是改变了以下几点:
change php.inito...
更改php.ini为...
memory_limit = 128M
and add to httpd.conf
并添加到 httpd.conf
RLimitMEM 1073741824 2147483648
and restart apache & i removed the error :
并重新启动 apache & 我删除了错误:
回答by Matt Humphrey
Could be an issue with MySQL and the number of open connections, hence why it sorts itself out when you restart every few days. Are they auto closing on script shutdown?
可能是 MySQL 和打开连接数的问题,因此当您每隔几天重新启动时它会自行解决。它们是否在脚本关闭时自动关闭?
回答by symcbean
Just to recap (I'm adding this answer quite a distance from the original question):
简单回顾一下(我添加的这个答案与原始问题相距甚远):
- PHP is unable to allocate what appears to be a small amount of memory
- the current memory usage at the time the error occrs + the requested amount is less than the memory limit currently in force
- the system has 6Gb available for use by PHP when this occurs
- since the problem is resolved by restarting apache - it's apache which is preventing the memory from beig available to PHP
- PHP 无法分配看似少量的内存
- 错误发生时的当前内存使用量 + 请求的数量小于当前有效的内存限制
- 发生这种情况时,系统有 6Gb 可供 PHP 使用
- 因为问题是通过重新启动 apache 解决的——它是 apache,它阻止了内存对 PHP 可用
If these are all valid then the only possible explanation is that the 6Gb is veryfragmented - which I think is a little unlikely. You didn't say how PHP is invoked from Apache - mod_php? fpm? Fcgi?
如果这些都是有效的,那么唯一可能的解释是 6Gb非常分散 - 我认为这有点不太可能。你没说PHP是怎么从Apache调用的——mod_php?fpm?Fcgi?
I would start by examining each of the above predicates - particularly the free memory one. How do you know that there's 6Gb free when the error occurs? A more likely cause is that there's a memory leak occurring which you're not spotting.
我将首先检查上述每个谓词 - 特别是空闲内存的谓词。发生错误时,您如何知道有 6Gb 可用?更可能的原因是发生了您没有发现的内存泄漏。
You've not provided any details of how apache is configured; I'd also have a look at reducing MaxRequestsPerChild and MaxMemFree. (I'm not very familiar with worker apache where this will apply per thread - really you need a limit per process). If you provided the core setting from the apache config then maybe we could make further suggestions.
您尚未提供有关如何配置 apache 的任何详细信息;我还想看看减少 MaxRequestsPerChild 和 MaxMemFree。(我对工作 apache 不是很熟悉,这将适用于每个线程 - 每个进程确实需要一个限制)。如果您提供了 apache 配置中的核心设置,那么也许我们可以提出进一步的建议。
Unless you are using Ajax extensively, make sure your keepalive time is 2 or less.
除非您广泛使用 Ajax,否则请确保您的 keepalive 时间为 2 或更少。
回答by Bilyaminu K
Fatal error: Out of memory (allocated SOLVED
i had similar problem, for months no solution. finally i was checking in one of the apache folders i.e(\apache\conf\extra) i came across this file that controls the memory allocation of apache. the file name is httpd-mpmin that file you are to increase the MaxMemFree which is set 2048 to something higher, i took mine to 10000 for the first MaxMemFree (IfModule !mpm_netware_module) then made the second one MaxMemFree to 5000 IfModule mpm_netware_module.
致命错误:内存不足(已分配已解决,
我遇到了类似的问题,几个月没有解决方案。最后我检查了其中一个 apache 文件夹 ie(\apache\conf\extra) 我遇到了这个控制 apache 内存分配的文件. 该文件中的文件名是httpd-mpm,您要将 MaxMemFree 设置为 2048 更高,我将第一个 MaxMemFree 设置为 10000(IfModule !mpm_netware_module),然后将第二个 MaxMemFree 设置为 5000 IfModule mpm_netware_module。
These solved my problem. hope it helps
这些解决了我的问题。希望能帮助到你

