【发布时间】:2012-08-14 11:30:10
【问题描述】:
由于我的问题越来越长,我决定重写整个问题以使其更好更短。
我在具有 8GB 内存的专用服务器上运行我的网站。我完全知道我需要提高 php.ini 设置的内存限制。我已将其从 128M 设置为 256M 和 -1。问题仍然是持久性。
致命错误:内存不足(已分配 786432)(试图分配 24576 字节)在 D:\www\football\views\main.php 第 81 行
内存不足没有意义,因为它说只分配了 786432 字节,而且还需要 24576 字节。
786432 字节只有 768 KB,而且相当小。
提示
- 错误发生在非常随机的行上。它并不总是在第 81 行出错。
- 在高峰期,Apache 只占用大约 500mb 的内存。我还有 6GB 可用空间。
- 没有无限循环。
- 脚本占用 1,042,424 字节。从
echo memory_get_peak_usage();获取此号码 - MySQL 的结果集很小(最多 12 行,纯文本,无 blob 数据)
- (重要)如果我每两天重新启动一次Apache,错误就消失了。这通常发生在 Apache 运行超过 2 天时。
- 我已包含分析脚本,您可以通过here 获取它。
- 这个专用服务器纯粹是用来运行一个网站的。该网站是一个高流量网站,平均每分钟有 1,000 名访问者。在高峰期,将有 1,700 到 2,000 名访客同时访问。
服务器规格
操作系统:Windows 2008 R2 64 位
CPU:英特尔酷睿 i5 - 4 核
内存:8 GB
阿帕奇 2.2
PHP 5.3.1
存储:2 x 1 TB 硬盘
带宽:每月 10 TB
解决方案
我终于调整并解决了这个问题,我想在这里分享我为改进所做的工作:
-
favicon.ico丢失了,这弄乱了我的路由引擎。虽然我的路由引擎很小,但是通过包含favicon.ico,它有助于通过不运行我的路由引擎来减少内存使用。我网站的大部分部分都有它,但我忘了把它放在这个新部分。 -
限制
MaxRequestPerChild有帮助。在我的另一台专用服务器中,我的MaxRequestPerChild有限。对于这个服务器,我设置为0。我一直以为每个脚本都是隔离的。假设我的脚本需要 800kb 才能运行。完成后,Apache 或 PHP 应该释放 800kb 内存。似乎它不以这种方式工作。有限MaxRequestPerChild确实有助于防止内存泄漏,方法是在有限MaxRequestPerChild之后创建新进程并且旧进程正在死亡。这是我的新设置。ThreadsPerChild 1500 MaxRequestsPerChild 10000 ob_flush();确实会稍微减少更多内存。它没有多大帮助,但每一点优化都有帮助。- 我使用了
xdebug,正如试图回答这个问题的人所建议的那样,我以前从未使用过。我不得不说它是一个很棒的工具,我已经优化了一些东西,让它运行得更快。 - 我禁用了一些不必要的 Apache 模块。我正在尝试一一禁用它,并对其进行几天的测试,以确保它在禁用另一个之前完美运行。我现在确实禁用了所有不必要的 PHP 扩展。
- 我在此服务器中的大部分脚本都使用传统方式(无模板、无数据库层、纯 PHP、HTML 和遗留 mysql_* 函数)。老实说,它运行速度非常快,而且使用的内存非常小。但是,由于网站越来越长,维护脚本并不容易。我试图将网站的某些部分转换为适当的框架(我自己的小框架)。我使用自己的框架的原因是它很小(整个框架只有 3kb,只包含我需要的内容)。
- 切换到 IIS7.5 彻底解决了这个问题。
【问题讨论】:
-
我闻到无限循环的味道。 :) 什么版本的 PHP?以及第 81 行的代码怎么样。
-
绝对值得支持 Leigh /\
-
仅仅因为它在 70% 的时间内都有效,并不意味着某些输入或变量不会使火车驶离轨道并杀死村民。我相当肯定火车是一个无限循环。 :D
-
我记得也遇到过类似的问题,是因为我使用了一个循环,使用doctrine往数据库中插入了一些数据,每次迭代,他都在数据库中打开了一个游标!
-
让我们开箱即用地思考一下。你对apache进程有任何内存限制吗?是否有任何
ulimit有效(可能是 www 用户或 PHP 脚本的所有者,例如在 .profile 中)?您是否尝试过在 Apache 模块中停止工作后立即在 CLI 中运行该脚本?您是否使用任何缓存机制 PHP 模块?您是否使用 suhosin 或类似的强化模块?