php内存回
Ⅰ 有人研究过php的内存回收机制吗
表示不敢研究...
php垃圾回收机制GC,每个版本都在更新...你研究他干嘛!直接研究内存原理就行了....
php.ini的内存主要是防止,php占用超过系统内存,造成死机...
配置文件里的内存只是单次解释占用的内存....
cup和内存的消耗的关系有一个临界点....就是最优值,
只想效率就是假设内存无限大,io带宽无限大,cpu缓存无限大的情况,cpu占用无限小....
Ⅱ 如何获知PHP程序占用多少内存memory
PHP性能优化过程中需要获取PHP内存消耗,使用memory_get_usage()函数可获取当前的内存消耗情况,函数使用简单,这里讨论一下memory_get_usage()函数的用法与实例
三,基础用法与实例
1,获取当前的内存消耗量
复制代码代码如下:
<?php
echo memory_get_usage();
$var = str_repeat("liuhui", 10000);
echo memory_get_usage();
unset($var);
echo memory_get_usage();
?>
分别输出:62328 122504 62416
说明:memory_get_usage()函数输出的数值为bytes单位
2,格式化memory_get_usage()输出
复制代码代码如下:
<?php
function convert($size){
$unit=array('b','kb','mb','gb','tb','pb');
return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
}
echo convert(memory_get_usage(true));
?>
输出:256 kb
3,自定义函数获取数组或变量值大小
复制代码代码如下:
<?php
function array_size($arr) {
ob_start();
print_r($arr);
$mem = ob_get_contents();
ob_end_clean();
$mem = preg_replace("/\n +/", "", $mem);
$mem = strlen($mem);
return $mem;
}
$memEstimate = array_size($GLOBALS);
?>
Ⅲ php内存分配怎么理解
1、内存检查,如果太大则报错
2、如果命中缓存,则使用fastcache中内存块
3、在zendMM中heap层根据申请大小从小块内存、大块内存、剩余内存中查找合适内存
4、如果还没合适的,则直接再申请一块内存
5、重设heap状态
6、返回内存地址、标志变量维护
Ⅳ php 内存不够怎么解决
这个提示的意思是内存条和磁盘空间太小,系统分配临时缓存的空间也随之不足,使你在运行一些程序时受到了缓存的限制。比方你在打游戏时是一关一关的往前打,你的电脑就要把你打过的游戏暂时保存在这个虚拟内存里。如果空间存储已满,那么你正在运行中的程序就会受到一些限制。
要解决虚拟内存太低的问题,只有把内存条和磁盘的容量扩大,一般内存条要达到1gb以上,磁盘也要达到80g的才好用。建议你只花几十元加一条内存条问题就全解决了。
如果你要手动将虚拟内存的缓存空间指定到其它盘符上是没有多大效果的。因为造成此问题的主要原因就是你的这些空间太小,使你的系统在合理分配时受到了限制。所以,你使用手动强迫手段来调配完全是错误的,相反,这样对你的电脑或更有所不利。
如果
你的确要手动调整,方法是:鼠标指向“我的电脑”弹右键——单击“属性”——单击“高级”——单击“性能”这里的“设置”——单击“高级”——单击“虚拟内存”这里的“更改”——在上面的列表中选择你要将虚拟内存更改到哪个盘,(选择剩余空间比较大的磁盘,一般的是e盘)——单击“自定义大小
”——输入最大值和最小值(把最大值改为物理内存的2.5倍)——点击右下角的“设置”按钮
——这时会弹出“重新启动计算机”的提示——单击“确定”重启即可
Ⅳ 查看PHP程序占用多少内存
想要知道编写的 PHP 脚本需要占用多少内存么?很简单,直接使用 PHP 查看当前分配给 PHP 脚本的内存的函数 memory_get_usage() 就可以了$memory = round(memory_get_usage() / 1024 / 1024, 2).'MB';
上面的程序默认输出单位为 byte(s))我将它转换成MB,也就是当时 PHP 脚本使用的内存(不含 memory_get_usage() 函数本身占用的内存)。
更多问题可以去php中文网问答社区提问http://www.php.cn/wenda.html,大神在线帮你解决,希望对你有帮助
Ⅵ PHP处理内存问题,怎么解决
最简单或常用的方法是修改php.ini
首先找到对你的网站生效的php.ini文件
由于有多个地方都可以设置php的参数,找到正确的配置文件,并进行更改是首先要做的一步。如果你上面的方法建立了php文件来查看其配置参数,则你可以找到"Loaded Configuration File"这一项,以下是个例子:
对于Linux用户,你可以通过执行"php -i | grep Loaded Configuration File"来找到对应的配置文件。而Windows用户,你可以尝试修改你的php安装目录下的php.ini。
编辑php.ini
在php.ini中,找到"memory_limit"这一项,如果没有,你可以在文件的尾部自己增加这个参数。以下是一些设置范例
memory_limit = 128M ; 可以将128M改为任何你想设置的值保存文件
重启web 服务器
如果是web服务器使用Apache, 则执行:
httpd restart
有些情况下,你可能不被允许私修改php.ini。比如如果你购买了虚拟主机服务,但是你的服务商确禁止你修改这个文件。那么,你可以需要考虑用其他方法来增加memory_limit的值。
Ⅶ php内存不足
你好
时候我们再运行php程序时,会出现
Allowed memory size of 8388608 bytes exhausted (tried to allocate 1298358 bytes)
出现该错误的原因:在确保不是程序产生的原因(例如死循环),是由于php页面消耗的最大内存默认是为 8M (在PHP的ini件里可以看到) ,
如果文件太大 或图片太大 在读取的时候 会发生上述错误。
解决办法:
1.修改 php.ini将memory_limit由 8M 改成 16M(或更大),重启apache服务
2.在PHP 文件中 加入 ini_set(‘memory_limit',‘**M');注意:为了系统的其它资源的正常使用 请您不要将 memory_limit设置太大,其中-1为不限
3.修改.htaccess 文档(前提是该目录支持.htaccess)在文档中新增一句:php_value memory_limit 16M(或更大)
满意请采纳
Ⅷ php 难题 内存占用
两个概念不同,函数获取是PHP.EXE(或者你的HTTPD.EXE)给此脚本分配的内存,而操作系统分配给进程的内存会大很多,我下面的没有使用任何变量的简单语句脚本,就两个语句,一个输出内存使用,一个暂停一下,程序显示脚本分陪内存100多K,而操作系统显示3M,如下图:
当然,你可以看看你的简单脚本占用内存多少,上G确实太惊人了。
Ⅸ PHP命令执行PHP脚本,结束之前,内存会回收吗
再详细说下问题:
unix下,用php命令来执行php脚本,在php结束之前,内存有没有机会被回收?新的GC算法有没有机会被调用?
出现这个问题,是因为线上有个离线数据导入脚本,需要把几千万行数据筛选入库,发现,在执行过程中,到达一定程度,就会抛出内存使用超过最大值。
1Fatalerror:
那第一想到的就是程序是不是有什么bug,造成内存超出,看了半天没有发现问题,于是,突然出现了这个疑问。那要解决这个疑问,最好的办法就去翻源码吧。
在之前我这么说:
都知道,PHP5.3有了新的垃圾回收机制:GC,它不是重点,不谈它的原理。
经过翻阅PHP源码,发现,调用这个的时机是在main/main.c::php_request_shutdown这个函数中,
12/*7.Shutdownscanner/executor/compilerandrestoreinientries*/zend_deactivate(TSRMLS_C);
php_request_shutdown,通过名字就能看出,它是在php请求结束的时候执行的,在这里会执行gc_collect_cycles来清理内存。
其实这句话是没错,但它只针对于SAPI接口(之前我就错在这个地方。),在用PHP命令执行php脚本的时候,是不会执行这个php_request_shutdown的。
那回到最初的问题,过程中到底有没有执行GC呢?
为了更直观有效的知道答案,我选择了最BT,最暴力的方法,拦截gc_collect_cycles,输出error_log到文件,只要执行了,
那肯定会输出log来。
重新编译PHP后,果不其然,符合官方的说法,只要buckets满超过默认值1000,就会启动GC来清理没用的内存,防止内存泄露。
那问“什么时间触发的GC呢?”,答“buckets超过1000的时候啊”,这不屁话嘛,要的是真真正正的执行流程,so。。不断的debug,
不断的grep,不断的step,不断的C+T,终于搞清楚了。下面就来根据官方的说法详细谈谈,PHP到底是怎么触发的。
有一点要注意,PHP的命令入口和sapi接口的入口是不同的,我就载在这个地方,以为都公用一个。
测试代码以官方文档为例:
1234567891011121314<?phpclassFoo{public$var='3.1415962654';}for($i=0;$i<=1000000;$i++){$a=newFoo;$a->self=$a;}echomemory_get_peak_usage()," ";?>
这样的代码,在PHP5.3之前,肯定会造成大量的内存泄露,不过,谁在开发时又能开发出这么变态的代码来?除非这个人很变态。^.*
那PHP的命令入口是什么?流程又是什么?
主要函数流程如下:
入口main函数(sapi/cli/php_cli.c)==》php_execute_script(main/main.c)==>zend_execute_scripts(Zend/zend.c)==>execute(Zend/zend_vm_execute.h)
调用GC的地方在execute里。
简单描述下这个过程,
main是入口,它的作用是根据我们传递的参数做不同的设置,最后会把我们的php脚本作为一个zend_file_handle指针传递给
php_execute_script函数,zend_file_handle其实就是把FILE*做了一下封装,保存了一些其他的文件信息。
php_execute_script会做一些文件检查工作,把php脚本加到哈希表included_files中。
php_execute_scripts会执行zend_compile_file函数来解释我们写的PHP代码,最后执行execute。
应该都知道Zend把脚本解析完会生成op代码保存到哈希表:active_op_array中,execute会逐个执行每个op,
op基本上都对应一个ZEND_ASSIGN_*_HANDLER这样的一个宏,它就保存在active_op_array->opline->handlers中。
在进入到execute之后:
首先初始化execute_data,它保存了很多重要信息,上下文信息,然后调用ZEND_VM_SET_OPCODE宏,
把execute_data->opline的指针指向active_op_array->opline->handlers。
之后,execute会执行一个while循环,逐条执行opline:
(1){intret;#ifdefZEND_WIN32if(EG(timed_out)){zend_timeout(0);}#endifif((ret=EX(opline)->handler(execute_dataTSRMLS_CC))>0){switch(ret){case1:EG(in_execution)=original_in_execution;return;case2:op_array=EG(active_op_array);gotozend_vm_enter;case3:execute_data=EG(current_execute_data);default:break;}}}
每个handlers都会执行一个宏:ZEND_VM_NEXT_OPCODE(),它意思就是跳到下一个Opline,这样就能逐条执行了。
最后跟踪上面的PHP代码会执行ZEND_ASSIGN_SPEC_CV_VAR_HANDLER这个宏,它是干嘛的?他就是变量赋值
下面代码执行的操作:
1234classA{}$a=newA();
这里就会执行这个宏。
在这个宏里有段代码:
_FASTCALLZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS){zend_op*opline=EX(opline);zend_free_opfree_op2;zval*value=_get_zval_ptr_var(&opline->op2,EX(Ts),&free_op2TSRMLS_CC);zval**variable_ptr_ptr=_get_zval_ptr_ptr_cv(&opline->op1,EX(Ts),BP_VAR_WTSRMLS_CC);if(IS_CV==IS_VAR&&!variable_ptr_ptr){if(zend_assign_to_string_offset(&EX_T(opline->op1.u.var),value,IS_VARTSRMLS_CC)){if(!RETURN_VALUE_UNUSED(&opline->result)){EX_T(opline->result.u.var).var.ptr_ptr=&EX_T(opline->result.u.var).var.ptr;ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr,Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset,1,1);}}elseif(!RETURN_VALUE_UNUSED(&opline->result)){AI_SET_PTR(EX_T(opline->result.u.var).var,EG(uninitialized_zval_ptr));PZVAL_LOCK(EG(uninitialized_zval_ptr));}}else{value=zend_assign_to_variable(variable_ptr_ptr,value,0TSRMLS_CC);if(!RETURN_VALUE_UNUSED(&opline->result)){AI_SET_PTR(EX_T(opline->result.u.var).var,value);PZVAL_LOCK(value);}}/*zend_assign_to_variable()alwaystakescareofop2,neverfreeit!*/if(free_op2.var){zval_ptr_dtor(&free_op2.var);};ZEND_VM_NEXT_OPCODE();}
free_op2.var保存的是newA的对象.
free_op2.var这个是哪儿来的呢?
在整个execute期间,维持一个execute_data结构,里面有个Ts指针
1union_temp_variable*Ts;
它用来保存一些临时的变量信息,比如newA(),这个会保存到Ts链表里,
opline->op2.u.var这个里面保存了此临时变量所在的位置,然后Ts+这个值是一个zval*指针,它就保存了newA产生的对象.
在代码中
1if(free_op2.var){zval_ptr_dtor(&free_op2.var);};
zval_ptr_dtor会根据free_op2.var的值执行到Zend/zend_execute_API.c::_zval_ptr_dtor函数中,
_APIvoid_zval_ptr_dtor(zval**zval_ptrZEND_FILE_LINE_DC)/*{{{*/{zval*zv=*zval_ptr;#ifDEBUG_ZEND>=2printf("Recingrefcountfor%x(%x):%d->%d ",*zval_ptr,zval_ptr,Z_REFCOUNT_PP(zval_ptr),Z_REFCOUNT_PP(zval_ptr)-1);#endifZ_DELREF_P(zv);if(Z_REFCOUNT_P(zv)==0){TSRMLS_FETCH();if(zv!=&EG(uninitialized_zval)){GC_REMOVE_ZVAL_FROM_BUFFER(zv);zval_dtor(zv);efree_rel(zv);}}else{TSRMLS_FETCH();if(Z_REFCOUNT_P(zv)==1){Z_UNSET_ISREF_P(zv);}GC_ZVAL_CHECK_POSSIBLE_ROOT(zv);}}
GC_ZVAL_CHECK_POSSIBLE_ROOT(zv);
它就是最终GC算法执行的地方.
gc_collect_cycles就在这个宏中执行了..
所以..
回到上面的问题,
php无论在SAPI接口或命令端,都会执行GC算法来进行垃圾内存回收.
Ⅹ php的最大内存限制是多少
这个看情况了,处理大数据肯定需要的内存更大,只是本地调试肯定用不了多少。
php.ini的内存限制默认为memory_limit = 128M,只要把memory_limit设为-1,就不会限制你跑cli脚本时的内存限制。
一般作为一台专门运行php的服务器,肯定要尽可能的把内存给于php运行,一台不够就追加。