在我目前正在研究的系统中,有一个进程将大量数据加载到数组中以进行排序/聚合/等等。我知道这个过程需要优化内存使用,但在短期内它只需要工作。
考虑到加载到数组中的数据量,我们不断达到内存限制。它已经增加了好几次,我想知道增加它通常是一个坏主意吗?或者仅是机器有多少RAM?
该机器有2GB的RAM,memory_limit目前设置为1.5GB。我们可以轻松地为机器添加更多RAM(无论如何都会这样)。
有其他人遇到过这种问题吗?什么是解决方案?
答案 0 :(得分:55)
作为Apache模块运行到服务器网页的PHP memory_limit
的配置必须考虑到您可以在计算机上同时拥有多少Apache进程 - 请参阅MaxClients
Apache的配置选项。
如果MaxClients
为100并且您有2,000 MB或RAM,则非常快速的计算将显示您不应使用超过20 MB *(因为20 MB * 100客户端= 2 GB或RAM,即服务器的总内存量)*表示memory_limit值。
这并没有考虑到可能在同一台服务器上运行其他东西,比如MySQL,系统本身......而且Apache可能已经为自己使用了一些内存。
当然,这也是一个“最糟糕的情况”,认为每个PHP页面都使用了最大的内存量。
在您的情况下,如果您只为一个作业需要如此大量的内存,我不会增加作为Apache模块运行的PḦP的memory_limit
。
相反,我会从命令行(或通过cron作业)启动该作业,并在这个唯一的情况下指定更高的memory_limit
具体。
这可以通过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执行定义多个值,您还可以使用-c
选项告诉它使用另一个配置文件,而不是默认的php.ini:
php -c /etc/phpcli.ini temp.php
那样,你有:
/etc/php.ini
适用于Apache,memory_limit
,低max_execution_time
,... /etc/phpcli.ini
几乎没有限制这可以确保您的批次能够投放 - 而且您的网站仍然具有安全性(memory_limit
和max_execution_time
是安全措施)
不过,如果你有时间优化脚本,你应该;例如,在你必须处理大量数据的那种情况下,分页是必须的; - )
答案 1 :(得分:2)
您是否尝试将数据集拆分为较小的部分,并且当时只处理一个部分?
如果从磁盘文件中获取数据,则可以使用fread()
函数加载较小的块,或者在数据库中加载sort of unbuffered db query。
自v3.something以来我没有检查过PHP,但你也可以使用某种形式的云计算。 1GB数据集似乎足够大,可以在多台机器上处理。
答案 2 :(得分:1)
鉴于您知道脚本存在需要修复的内存问题,并且您只是在寻找短期解决方案,那么我将不介绍go about profiling解决内存问题的方法。听起来你会想到这一点。
所以,我想说你要记住的主要事情是:
PHP只是系统的一个小组件。如果你允许它占用大量的RAM,那么其他进程将受到影响,这反过来又会影响脚本本身。值得注意的是,如果您从数据库中提取大量数据,那么您的DBMS可能需要大量内存才能为查询创建结果集。作为快速修复,您可能希望识别正在运行的任何查询并尽快释放结果,以便为长时间的工作提供更多内存。
就操作系统功能而言,您应该记住,您可能正在运行的32位系统只能处理高达4GB的RAM而无需特殊处理。通常,限制可以少得多,具体取决于它的使用方式。有些Windows芯片组和配置实际上可用于系统可用的不到3GB,即使物理安装了4GB或更多。您应该检查系统可以解决的问题。
你说你已经多次增加内存限制,所以显然这项工作的范围越来越大。如果你高达1.5Gb,那么即使安装2Gb更多的RAM听起来就像它只是一个短暂的缓解。
让其他人遇到过这种情况 问题?什么是解决方案?
我想你可能已经知道,唯一真正的解决方案是分解并花时间尽快优化脚本,否则你最终会得到一个太大而无法运行的工作。