实践出php内存极限phpfpm占用内存是多少

PHP什么时候释放内存??? - ITeye问答
经测试,unset,和=null都不能够达到释放内存的效果。即不是立即释放。
请问在将变量unset或=null之后,变量之前引用的内存空间什么时候释放?还是说只能等待系统回收?
问题补充:xieye 写道程序执行完应该回收吧
那就是程序执行完成之前内存空间一直被占用???我unset,=null之后发现进城的内存空间没有释放。
有的情况下PHP所执行的查询或其他操作会占用很大的内存,如多次进行查询操作并且返回很大的数据集,这时就需使用mysql_free_result()函数手动释放内存。函数定义为:
int mysql_free_result( int result)。
该函数的使用很简单,不再详述。
PHP 无法手动释放内存,你 unset 了,也要等 GC 来自动回收,这个不是 C语言, 内存是 PHP 来管理的。
这个只能是加大内存,或者改用其他内存占用小的算法
摘要 内存管理对于长期运行的程序,例如服务器守护程序,是相当重要的影响;因此,理解PHP是如何分配与释放内存的对于创建这类程序极为重要。本文将重点探讨PHP的内存管理问题。
  一、 内存
  在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = 'hello world '; ?>"即可,并且该字符串能够被自由地修改、拷贝和移动。而在C语言中,尽管你能够编写例如"char *str = "hello world ";"这样的一个简单的静态字符串;但是,却不能修改该字符串,因为它生存于程序空间内。为了创建一个可操纵的字符串,你必须分配一个内存块,并且通过一个函数(例如strdup())来复制其内容。
{
 char *
 str = strdup("hello world");
 if (!str) {
  fprintf(stderr, "Unable to allocate memory!");
 }
}
  由于后面我们将分析的各种原因,传统型内存管理函数(例如malloc(),free(),strdup(),realloc(),calloc(),等等)几乎都不能直接为PHP源代码所使用。
  二、 释放内存
  在几乎所有的平台上,内存管理都是通过一种请求和释放模式实现的。首先,一个应用程序请求它下面的层(通常指"操作系统"):"我想使用一些内存空间"。如果存在可用的空间,操作系统就会把它提供给该程序并且打上一个标记以便不会再把这部分内存分配给其它程序。
当应用程序使用完这部分内存,它应该被返回到OS;这样以来,它就能够被继续分配给其它程序。如果该程序不返回这部分内存,那么OS无法知道是否这块内存不再使用并进而再分配给另一个进程。如果一个内存块没有释放,并且所有者应用程序丢失了它,那么,我们就说此应用程序"存在漏洞",因为这部分内存无法再为其它程序可用。
  在一个典型的客户端应用程序中,较小的不太经常的内存泄漏有时能够为OS所"容忍",因为在这个进程稍后结束时该泄漏内存会被隐式返回到OS。这并没有什么,因为OS知道它把该内存分配给了哪个程序,并且它能够确信当该程序终止时不再需要该内存。
  而对于长时间运行的服务器守护程序,包括象Apache这样的web服务器和扩展php模块来说,进程往往被设计为相当长时间一直运行。因为OS不能清理内存使用,所以,任何程序的泄漏-无论是多么小-都将导致重复操作并最终耗尽所有的系统资源。
  现在,我们不妨考虑用户空间内的stristr()函数;为了使用大小写不敏感的搜索来查找一个字符串,它实际上创建了两个串的各自的一个小型副本,然后执行一个更传统型的大小写敏感的搜索来查找相对的偏移量。然而,在定位该字符串的偏移量之后,它不再使用这些小写版本的字符串。如果它不释放这些副本,那么,每一个使用stristr()的脚本在每次调用它时都将泄漏一些内存。最后,web服务器进程将拥有所有的系统内存,但却不能够使用它。
  你可以理直气壮地说,理想的解决方案就是编写良好、干净的、一致的代码。这当然不错;但是,在一个象PHP解释器这样的环境中,这种观点仅对了一半。
  三、 错误处理
  为了实现"跳出"对用户空间脚本及其依赖的扩展函数的一个活动请求,需要使用一种方法来完全"跳出"一个活动请求。这是在Zend引擎内实现的:在一个请求的开始设置一个"跳出"地址,然后在任何die()或exit()调用或在遇到任何关键错误(E_ERROR)时执行一个longjmp()以跳转到该"跳出"地址。
  尽管这个"跳出"进程能够简化程序执行的流程,但是,在绝大多数情况下,这会意味着将会跳过资源清除代码部分(例如free()调用)并最终导致出现内存漏洞。现在,让我们来考虑下面这个简化版本的处理函数调用的引擎代码:
void call_function(const char *fname, int fname_len TSRMLS_DC){
 zend_function *
 char *lcase_
 /* PHP函数名是大小写不敏感的,
 *为了简化在函数表中对它们的定位,
 *所有函数名都隐含地翻译为小写的
 */
 lcase_fname = estrndup(fname, fname_len);
 zend_str_tolower(lcase_fname, fname_len);
 if (zend_hash_find(EG(function_table),lcase_fname, fname_len + 1, (void **)&fe) == FAILURE) {
  zend_execute(fe->op_array TSRMLS_CC);
 } else {
  php_error_docref(NULL TSRMLS_CC, E_ERROR,"Call to undefined function: %s()", fname);
 }
 efree(lcase_fname);
}
  当执行到php_error_docref()这一行时,内部错误处理器就会明白该错误级别是critical,并相应地调用longjmp()来中断当前程序流程并离开call_function()函数,甚至根本不会执行到efree(lcase_fname)这一行。你可能想把efree()代码行移动到zend_error()代码行的上面;但是,调用这个call_function()例程的代码行会怎么样呢?fname本身很可能就是一个分配的字符串,并且,在它被错误消息处理使用完之前,你根本不能释放它。
  注意,这个php_error_docref()函数是trigger_error()函数的一个内部等价实现。它的第一个参数是一个将被添加到docref的可选的文档引用。第三个参数可以是任何我们熟悉的E_*家族常量,用于指示错误的严重程度。第四个参数(最后一个)遵循printf()风格的格式化和变量参数列表式样。
程序执行完了之后,整个进程都没了,自然会释放。
无论是命令行的php,还是网页执行的php
程序执行完了释放
unset释放
析构函数释放
函数结束后局部变量释放
程序执行完应该回收吧
已解决问题
未解决问题测试php脚本内存占用量问题_php吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:119,540贴子:
测试php脚本内存占用量问题收藏
我现在在思考一个问题若大量使用static与new 相比会不会在高并发的时候节省内存我现在做测试
memary_get_usage返回的一直是512kb
上市公司「达内」全新php开发课程,以实战为主线,穿插php理论教学.取证+就业一步到位,14年经验,20W毕业学员,用实力说话!名企直通班招生中,88天月薪即可月薪上万,免费试听!
static是直接写入内存,节省的cpu,new 太多了 浪费内存节省cpu,还是结合使用吧
php并不是你用多少它取多少内存。而是它会一次取固定的量,不管你有没有用到那么多
实例对象的是数据(属性),多个对象占用的也是多份数据,代码只有一处,并不是说new一个对象把代码也copy一份,开销在PHP本身对dynamic对象维护包含内存和CPU建议别太在意这些,设计上的合理性要重要得多比如极端一点的话,数据全部是外面维护,所有方法都做成static那这个类和一个函数库有什么区别?
你说的是单态设计模式。这样确实会比较省CPU
new class的时候:class属性copyclass方法一份static class的时候:属性 方法都是一份单例模式情况下:每个class只有一份这样内存的差别就不会太大,结合使用是最好的
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 – 左手代码 右手诗
首先让我们看一个问题: 如下代码的输出,
var_dump(memory_get_usage());
$a = &laruence&;
var_dump(memory_get_usage());
unset($a);
var_dump(memory_get_usage());
输出(在我的个人电脑上, 可能会因为系统,PHP版本,载入的扩展不同而不同):
int(90440)
int(90640)
int(90472)
注意到 =32, 于是就有了各种的结论, 有的人说PHP的unset并不真正释放内存, 有的说, PHP的unset只是在释放大变量(大量字符串, 大数组)的时候才会真正free内存, 更有人说, 在PHP层面讨论内存是没有意义的.
那么, 到底unset会不会释放内存? 这32个字节跑哪里去了?
要回答这个问题,
我将从俩个方面入手:
这32个字节去哪里了
首先我们要打破一个思维: PHP不像C语言那样, 只有你显示的调用内存分配相关API才会有内存的分配.
也就是说, 在PHP中, 有很多我们看不到的内存分配过程.
$a = &laruence&;
隐式的内存分配点就有:
1. 为变量名分配内存, 存入符号表
2. 为变量值分配内存
所以, 不能只看表象.
第二, 别怀疑,PHP的unset确实会释放内存(当然, 还要结合引用和计数, 这部分的内容请参看我之前的文章), 但这个释放不是C编程意义上的释放, 不是交回给OS.
对于PHP来说,
它自身提供了一套和C语言对内存分配相似的内存管理API:
emalloc(size_t size);
efree(void *ptr);
ecalloc(size_t nmemb, size_t size);
erealloc(void *ptr, size_t size);
estrdup(const char *s);
estrndup(const char *s, unsigned int length);
这些API和C的API意义对应, 在PHP内部都是通过这些API来管理内存的.
当我们调用emalloc申请内存的时候, PHP并不是简单的向OS要内存, 而是会像OS要一个大块的内存, 然后把其中的一块分配给申请者, 这样当再有逻辑来申请内存的时候, 就不再需要向OS申请内存了, 避免了频繁的系统调用.
比如如下的例子:
var_dump(memory_get_usage(TRUE)); //注意获取的是real_size
$a = &laruence&;
var_dump(memory_get_usage(TRUE));
unset($a);
var_dump(memory_get_usage(TRUE));
int(262144)
int(262144)
int(262144)
也就是我们在定义变量$a的时候, PHP并没有向系统申请新内存.
同样的, 在我们调用efree释放内存的时候, PHP也不会把内存还给OS, 而会把这块内存, 归入自己维护的空闲内存列表. 而对于小块内存来说, 更可能的是, 把它放到内存缓存列表中去(后记, 某些版本的PHP, 比如我验证过的PHP5.2.4, 5.2.6, 5.2.8, 在调用get_memory_usage()的时候, 不会减去内存缓存列表中的可用内存块大小, 导致看起来, unset以后内存不变, 见评论).
现在让我来回答这32个字节跑哪里去了,
就向我刚才说的, 很多内存分配的过程不是显式的, 看了下面的代码你就明白了:
var_dump(&I am Laruence, From &);
var_dump(memory_get_usage());
$a = &laruence&;
var_dump(memory_get_usage());
unset($a);
var_dump(memory_get_usage());
string(43) &I am Laruence, From &
int(90808) //赋值前
int(90976)
int(90808) //是的, 内存正常释放了
= 0, 正常了, 也就是说这32个字节是被输出函数给占用了(严格来说, 是被输出的Header占用了)
只增不减的数组
Hashtable是PHP的核心结构(了解Hashtable, 可以参看我之前的文章), 数组也是用她来表示的, 而符号表也是一种关联数组, 对于如下代码:
var_dump(&I am Laruence, From &);
var_dump(memory_get_usage());
$array = array_fill(1, 100, &laruence&);
foreach ($array as $key =& $value) {
${$value . $key} = NULL;
var_dump(memory_get_usage());
foreach ($array as $key=& $value) {
unset(${$value . $key});
var_dump(memory_get_usage());
我们定义了100个变量,
然后又按个Unset了他们, 来看看输出:
string(43) &I am Laruence, From &
int(93560)
int(118848)
int(104448)
Wow, 怎么少了这么多内存?
这是因为对于Hashtable来说, 定义它的时候, 不可能一次性分配足够多的内存块, 来保存未知个数的元素, 所以PHP会在初始化的时候, 只是分配一小部分内存块给HashTable, 当不够用的时候再RESIZE扩容,
而Hashtable, 只能扩容, 不会减少, 对于上面的例子, 当我们存入100个变量的时候, 符号表不够用了, 做了一次扩容, 而当我们依次unset掉这100个变量以后, 变量占用的内存是释放了(118848 &#), 但是符号表并没有缩小, 所以这些少的内存是被符号表本身占去了…
现在, 你是不是对PHP的内存管理有了一个初步的认识了呢?
Related Posts:
Tags: , , , , , ,
Filed in ,
Leave a Reply
开发组核心成员, 顾问, PHP7主要开发者, , , 等开源项目作者.

我要回帖

更多关于 php查看内存占用 的文章

 

随机推荐