浅谈php内存管理机制,各位看官了解下~~~

    说到这个内存管理机制啊,咱先不废话,来看段代码:

<?php
//内存管理机制
var_dump(memory_get_usage());//获取内存方法,加上true返回实际内存,不加则返回表现内存
$a = "luyaran";
var_dump(memory_get_usage());
unset($a);
var_dump(memory_get_usage());
//输出(在我的个人电脑上, 可能会因为系统,PHP版本,载入的扩展不同而不同):
//int 122136
//int 122232
//int 122136

    大家可以自己运行下,看看输出的结果有何差异。在不同的平台或者环境中运行之后,大家可能会发现,定义变量之后,内存增加,清除变量之后,内存恢复(有些可能不会恢复和以前一样),好像定义变量时申请了一次内存。其实不是这样的,php会预先申请一块内存,而不会每次定义。

    接下来,我们来具体了解下。首先,我们要知道,PHP不像C语言那样, 只有你显示的调用内存分配相关API才会有内存的分配. 也就是说, 在PHP中, 有很多我们看不到的内存分配过程。比如对于$a = "luyaran";的隐式的内存分配点为: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 = "luyaran";
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以后内存不变,当然,这只是一些,更多的,期待大家的发现了哦。

    最后我们来看变量的定义。我们在定义变量时,存储两个方面的值。首先是变量名,存储在符号表,然后是变量值,存储在内存空间。不过我们在删除变量的时候,会将变量值存储的空间释放,而变量名所在的符号表不会减小(也可以叫做只增不减)。关于这个,我们可以通过数组来更加详细的了解。

    我们知道,Hashtable是PHP的核心结构, 数组也是用它来表示的, 而符号表也是一种关联数组。所以,我们如果要测试的话,就得先通过数组定义很多值,然后删掉来看效果,如下代码:

var_dump(memory_get_usage());
for($i=0;$i<100;$i++)
{
    $a = "luyaran".$i;
    $$a = "hello";
}
var_dump(memory_get_usage());
for($i=0;$i<100;$i++)
{
    $a = "luyaran".$i;
    unset($$a);
}
var_dump(memory_get_usage());

    运行结果如下所示:


    通过观察,相信大家也会发现,咱们最后得到的空间比原先定义的空间小了一些。这是因为对于Hashtable来说, 定义它的时候, 不可能一次性分配足够多的内存块, 来保存未知个数的元素, 所以PHP会在初始化的时候, 只是分配一小部分内存块给HashTable, 当不够用的时候再RESIZE扩容。而Hashtable, 只能扩容, 不会减少, 对于上面的例子, 当我们存入100个变量的时候, 符号表不够用了, 做了一次扩容, 而当我们依次unset掉这100个变量以后, 变量占用的内存是释放了(118848 – 104448), 但是符号表并没有缩小, 所以这些少的内存是被符号表本身占去了。

    好啦,这次分享就到这里了。关于这个hashtable,后续咱们再来了解哈。如果感觉不错的话,请多多点赞支持哦。。。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值