2009-09-15 77 views
35

在我目前工作的一个系统中,存在加载大量的数据到一个数组进行排序/聚集/不管一个进程。我知道这个过程需要优化内存使用,但在短期内它只需要工作。增加PHP memory_limit。它在什么时候变得疯狂?

鉴于数据加载到阵列的数量,我们不停的按内存限制。它已经增加了好几次,我想知道是否有一点增加它通常是一个坏主意?或者是只有这台机器有多少RAM?

该机具有2GB的RAM和memory_limit的当前设置在1.5GB。我们可以轻松地为机器添加更多内存(无论如何)。

有无其他人遇到这样的问题?以及解决方案是什么?

+6

老实说,你不应该关心设置内存限制,而是要弄清楚你的内存泄漏的位置并修复它。这不是一个增加memory_limit的解决方案,它避免了代码中的问题。看看你正在设置哪些对象并取消设置值以清除泄漏。 – Petrogad 2009-09-15 04:42:53

+0

你能具体说明数据量吗?你的意思是什么? – jergason 2009-09-15 04:43:23

+8

@Frederico:OP并没有试图解决内存泄漏问题,他正在寻求处理PHP中非常大的数据集的解决方案。 – arul 2009-09-15 04:49:17

回答

53

用于运行PHP作为Apache模块服务器网页的memory_limit的配置必须考虑到有多少Apache进程,你可以在同一时间在机器上 - 看到的Apache MaxClients配置选项。

如果MaxClients为100并且您有2,000 MB或RAM,则非常快速的计算将显示您不应该使用超过20 MB *(因为20 MB * 100客户端= 2 GB或RAM,即总数你的服务器有内存)*为memory_limit值。

这是没有考虑到有可能是在同一台服务器上运行,例如MySQL,系统本身,......其他的东西,Apache是​​否可能已经在使用一些内存本身。

或课程,这也是一个“最坏的情况”,即认为每个PHP页面使用的最大内存量就可以了。


在你的情况,如果你需要的内存这么大的量只有一个作业,我不会增加memory_limit为PHP运行的Apache模块。

相反,我会从启动命令行(或通过cron作业)那份工作,而在这其中,只有指定的情况下更高的memory_limit specificaly。

这可以用PHP的-d选项来完成,如:

$ php -d memory_limit=1GB temp.php 
string(3) "1GB" 

考虑,在这种情况下,temp.php只包含:

var_dump(ini_get('memory_limit')); 

在我看来,这是比增加Apache模块的PHP模块的memory_limit更安全 - 这就是我通常在做大数据集时所做的事情,或者一些非常重的东西,我无法优化或分页。


如果您需要为PHP CLI执行时定义几个值,你也可以告诉它使用而不是默认的PHP其他配置文件。INI,与-c选项:

php -c /etc/phpcli.ini temp.php 

这样一来,您有:

  • /etc/php.ini为Apache,低memory_limit,低max_execution_time ...
  • /etc/phpcli.ini的批次从命令运行 - 线,几乎没有限制

这确保您的批次将能够运行 - 而且你会还有安全为您的网站(memory_limitmax_execution_time是安全措施)


不过,如果你要优化你的脚本,你应该时刻;例如,在那种需要处理大量数据的情况下,分页是必须的;-)

+0

是的,只有在需要它的过程中才会提高限制。不幸的是,在这种情况下分页不会有帮助;最终的结果只有少数(20左右)的统计数字,只是需要空间的处理。 – 2009-09-15 05:11:16

+0

噢,好的......那么,我想这取决于你启动这个过程时有多少“免费”内存:如果你在半夜启动它,当几乎没有人使用你的服务器时,也许1.5 GB可能是好的(我会用更多的,让一些内存到系统的其他部分) - 但只有你可以说当时你的服务器加载了多少。 – 2009-09-15 05:23:15

+4

在某些PHP版本中(例如带有Suhosin-Patch的PHP 5.3.15),设置为1G,而不是1GB。测试它或PHP会将限制设置为最低值,并且脚本将无法执行,例如,使用'php -d memory_limit = 1G -r'echo ini_get('memory_limit');“' – 2013-03-20 14:12:11

2

您是否尝试将数据集分成较小的部分,并且只处理一部分?

如果您从磁盘文件中获取数据,则可以使用fread()函数在数据库中加载较小的块或某些sort of unbuffered db query

我从v3.something没有检查过PHP,但是你也可以使用云计算的一种形式。 1GB数据集看起来足够大,可以在多台机器上处理。

+0

该计划仅根据需要读取数据(正如您使用fread())所建议的那样,但这是我们尚未得到的重构。 – 2009-09-15 05:27:39

+0

这是实际的正确答案,IMNSHO:除非数据集完全相关,否则通常可以一次处理一个部分,并且很少有必要将其全部保存在内存中。正如OP所指出的那样,这通常需要不重构的重构。 – Piskvor 2015-12-15 10:06:40

1

鉴于您知道脚本中存在需要修复的内存问题,并且您只是在寻找短期解决方案,那么我将不会解决go about profiling和解决内存问题的方法。这听起来像你会去那。

所以,我说你要记住的主要事情是:在系统上

  • 总内存负载
  • 操作系统功能

PHP只是其中的小部分系统。如果你让它吃掉大量的RAM,那么其他进程就会受到影响,进而影响到脚本本身。值得注意的是,如果你从数据库中提取大量数据,那么你的DBMS可能需要大量内存才能为你的查询创建结果集。作为一种快速解决方案,您可能需要确定正在运行的任何查询并尽快释放结果,以便为长时间运行提供更多内存。

就操作系统功能而言,您应该记住,您可能正在运行的32位系统只能处理高达4GB的RAM,而无需特殊处理。取决于它的使用方式,限制通常要少得多。一些Windows芯片组和配置实际上可以有少于3GB的系统可用,即使是4GB或更多的物理安装。你应该检查你的系统能够处理多少。

你说你多次增加了内存限制,所以显然这个工作的范围越来越大。如果你达到1.5Gb,那么即使安装2Gb更多的内存,听起来也只是短暂的缓解。

有没有人遇到过这种类型的 问题?以及解决方案是什么?

我想你可能已经知道唯一真正的解决方案是分解并花时间尽快优化脚本,否则最终会导致工作量太大而无法运行。

+0

该机器非常专注于PHP,数据库服务器是分开的。以前的限制增加并不是因为工作在增加(虽然会增加,但不会那么快),但他们不足以“解决”问题(所以我们尝试了更大的限制)。我们现在有一个让流程运行的限制,但它绝对只是一个短期解决方案。关于系统限制的好处是,它是一个64位机器,无论如何我们都会增加RAM。无论如何,我认为你已经减轻了我​​的担心,即在一个过程中抛出这么多的记忆是荒谬的。 RDBMS是这样做的,为什么我不能:) – 2009-09-15 06:29:47