深入PHP内存相关的功能特性详解

可能有的读者碰到过类似下面的错误吧: Fatal error: Allowed memory size of X bytes exhausted (tried to
allocate Y
bytes)这个错误的信息很明确,PHP已经达到了允许使用的最大内存了,通常上来说这很有可能是我们的程序编写的有些问题。比如:一次性读取超大的文件到内存中,或者出现超大的数组,或者在大循环中的没有及时是放掉不再使用的变量,这些都有可能会造成内存占用过大而被终止。

报错提示:Fatal error: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 38218371 bytes) in …..

PHP默认的最大内存使用大小是32M,
如果你真的需要使用超过32M的内存可以修改php.ini配置文件的如下配置:

解决方法:

memory_limit =
32M如果你无法修改php配置文件,同时你的PHP环境没有禁用ini_set()函数,也可以动态的修改最大的内存占用大小:

1.取消PHP的内存限制。
在php程序中添加 ini_set(“memory_limit”,”-1″);
2.根据自己的需要及参考本机的内存大小修改php内存限制,如改为1024M。
在php程序中添加 ini_set(“memory_limit”,”1024M”);
或者将php.ini中相应位置改为memory_澳门新葡萄京娱乐场 ,limit = 1024M;

<?php ini_set(“memory_limit”,
“128M”);既然我们能动态的调整最大的内存占用,那我们是否有办法获取目前的内存占用情况呢?答案是肯定的。

内存限制的意义

1.memory_get_usage(),这个函数的作用是获取目前PHP脚本所用的内存大小。
2.memory_get_peak_usage(),这个函数的作用返回当前脚本到目前位置所占用的内存峰值,这样就可能获取到目前的脚本的内存需求情况。
单就PHP用户空间提供的功能来说,我们似乎无法控制内存的使用,只能被动的获取内存的占用情况

php中的相关文档解释 memory_limit 如下:

那么当我们知道php引用计数,函数表,符号表,常量表等,这些信息都会占用内存的时候

memory_limit: integer

我们可以有意的避免不必要的浪费内存,比如我们在项目中通常会使用autoload来避免一次性把不一定会使用的类包含进来,而这些信息是会占用内存的

该指令设定了一个脚本
所能够申请到的最大内存字节数。这有助于防止写得不好的脚本消耗光服务器上的可用内存。要使用此指令必须在编译的时候激活。因此
configure
一行中应该包括:–enable-memory-limit。如果不需要任何内存上的限制,必须将其设为
-1。 从 php 4.3.2 起,当激活了 memory_limit,PHP 函数
memory_get_usage() 便可以使用了。也就是说,php在一个 page
中的处理内存限制,默认的(/etc/php.ini)定义为 128M
(我的系统默认安装后),后来开发组的应用写的越来越复杂,但是在结构上可能还有些欠缺,频繁的对象请求,居然造成了内存不足。

如果我们及时把不再使用的变量unset掉之后可能会释放掉它所占用的空间

应用层面测试与解决方法

最好的方式应该在应用层面解决,而不是不断的增加内存设置。以下为代码测试:

 代码如下

<?
printf(” total run: %.2f s<br>”.
“memory usage: %.2f M<br> “,
microtime(true)-$HeaderTime,
memory_get_usage() / 1024 / 1024 );
?>

运行结果显示如下:

total runtime: 1.47 s

memory usage: 77.09 M

一个页面居然会有77M的请求。究其原因,是程序员在编码时,仅仅对变量赋值,却从来没有
unset ($var)
过。试想,如果一个页面请求要处理20个sql查询,每个sql查询返回10个sql结果,而程序员从来都不关心是返回一个row的所有column还是仅仅返回需要的column(实际上当我们采用更common的中间层时,往往会返回全部的column而不是特定的某几个字段,就像在
ORM 中如NHibernate, JBOSS中的那样)如果一条row有10K,
那么这个页面到处理结束时就要增加到
10K*10*20=2M的数组分配,这还不算有时候我们需要最数组进行复制。

所以在php中,合理的方法是变量使用后就
unset($var),最大限度节省内存资源。

经验之谈

本人有一台服务器使用的是apaceh2.3与php5.2.6上面的方法无效,经官方确认是php版本bug了,我们可以换个高版本手php版本即可解决。

发表评论

电子邮件地址不会被公开。 必填项已用*标注