zoukankan      html  css  js  c++  java
  • 关于PHP中的unset

    关于PHP的unset:

    关于unset是否真正释放内存的问题,在网上搜了一下,发现一些有意思的研究


    1.链接:http://bbs.chinaunix.net/archiver/?tid-1043649.html

    这里的代码展示了一下,unset之后,内存实际上并没有减少,而是分配给下一个使用的变量了。另外我计算了一下差值,在第10行算了一下第10行和第2行的差,稳定在712。


    [code]
     

         1 <?php
          2 echo memory_get_usage()."\n";
          3
          4 $a[]='a';
          5 unset($a);
          6 echo memory_get_usage()."\n";
          7
          8 $x[]='n';
          9 unset($x);
         10 echo memory_get_usage()."\n";
         11
         12 $c[]='a';
         13 unset($c);
         14 echo memory_get_usage()."\n";
         15 ?>
    [/code]

    结果是这样的
    50764          --->Start
    51152          --->定义$a并释放
    51152          --->定义$x并释放
    51152          --->定义$c并释放


    PHP是解释执行的过程
    定义$a一定导致一次内存分配
    定义$x也导致内存分配
    但内存使用量没有增加为什么  因为$a被释放了 $x使用的内存和$a一样正好使用了$a释放的内存

    是不是得出以下结论 :

    1  unset释放内存了释放的内存 还被整个脚本占用 以备复用

    2  PHP仅在结束时候将全部内存释放掉你不是放文件描述 数据库链接 也都会在此刻释放 不会导致资源泄漏

    以前我们在C程序里面分配的内存一定要自己释放否则就会泄漏 PHP中不需要了


    2.这里有一个更绝的代码:

    链接:http://hi.baidu.com/langwan/blog/item/e1e2d7c81cb446147f3e6f3a.html


    for ( $i = 1; $i < 100; $i++ ) {

    $str = str_repeat('01234567', $i);

    $a = memory_get_usage();

    unset($str);

    $b = memory_get_usage();

    echo "\n<br />".$i.': '.($b - $a).' Bytes.';

    }


    结果如下:


    1: 0 Bytes.
    2: 0 Bytes.
    ……
    30: 0 Bytes.
    31: 0 Bytes.
    32: -272 Bytes.
    33: -280 Bytes.
    ……
    98: -800 Bytes.
    99: -808 Bytes.



    跟在我机器上测试的结果一样,看来unset()对占用内存多的变量作用更明显,这应该是php内部的机制,变量占用内存少的情况下,unset并不真正 释放内存,因为这种占用内存小的变量(一般使用较为频繁)所导致的内存增加问题并不会太严重,只有对那些占用内存多的变量(一般使用频率低)才进行真正的 内存释放。


    另外,我把这个代码做了一下改动,发现很有意思的情况:


    改动1:

    for ( $i = 1; $i < 100; $i++ ) {

    $c = memory_get_usage();

    $a = memory_get_usage();

    $b = memory_get_usage();

    echo "\nAllocate:".$i.': '.($b - $a).' Bytes.';

    echo "\n".$i.': '.($b - $a).' Bytes.';

    }


    输出结果:

    Allocate:1: 136 Bytes.

    1: 136 Bytes.

    Allocate:2: 0 Bytes.

    2: 0 Bytes.

    Allocate:3: 0 Bytes.

    3: 0 Bytes.

    Allocate:4: 0 Bytes.

    4: 0 Bytes.

    Allocate:5: 0 Bytes.

    5: 0 Bytes.

    Allocate:6: 0 Bytes.

    ……



    第一次分配的空间应该是为$a,$b,$c,$i分配的内存,以后没有内存变化


    改动2:

    for ( $i = 1; $i < 100; $i++ ) {

    $c = memory_get_usage();

    $str = str_repeat('0123456',$i);

    $a = memory_get_usage();

    $b = memory_get_usage();

    echo "\nAllocate:".$i.': '.($a - $c).' Bytes.';

    echo "\n".$i.': '.($b - $a).' Bytes.';

    }


    输出:

    Allocate:1: 336 Bytes.

    1: 136 Bytes.

    Allocate:2: 0 Bytes.

    2: 0 Bytes.

    Allocate:3: 48 Bytes.

    3: 0 Bytes.

    Allocate:4: 56 Bytes.

    4: 0 Bytes.

    Allocate:5: 64 Bytes.

    5: 0 Bytes.

    Allocate:6: 0 Bytes.

    6: 0 Bytes.

    Allocate:7: 80 Bytes.

    7: 0 Bytes.

    Allocate:8: 88 Bytes.

    8: 0 Bytes.

    Allocate:9: 96 Bytes.

    9: 0 Bytes.

    Allocate:10: 104 Bytes.

    10: 0 Bytes.

    Allocate:11: 0 Bytes.

    11: 0 Bytes.

    Allocate:12: 120 Bytes.

    12: 0 Bytes.

    Allocate:13: 128 Bytes.

    13: 0 Bytes.

    Allocate:14: 136 Bytes.

    14: 0 Bytes.

    ……

    Allocate:30: 264 Bytes.

    30: 0 Bytes.

    Allocate:31: 272 Bytes.

    31: 0 Bytes.

    Allocate:32: 280 Bytes.

    32: 136 Bytes.

    Allocate:33: 8Bytes.

    33: 0 Bytes.

    Allocate:34: 8Bytes.

    34: 0 Bytes.

    Allocate:35: 8Bytes.

    35: 0 Bytes.

    ……


    从这里我们可以看出,从32开始是比较正常的结果,每次$str的空间增加8bytes

    改动3:

    for ( $i = 1; $i < 100; $i++ ) {

    $c = memory_get_usage();

    $str = str_repeat('0123456',$i);

    $a = memory_get_usage();

    unset($str);

    $b = memory_get_usage();

    echo "\nAllocate:".$i.': '.($a - $c).' Bytes.';

    echo "\n".$i.': '.($b - $a).' Bytes.';

    }


    输出:

    Allocate:1: 336Bytes.

    1: 96 Bytes.

    Allocate:2: 96Bytes.

    2: 0Bytes.

    Allocate:3: 48Bytes.

    3: 0Bytes.

    Allocate:4: 56Bytes.

    4: 0 Bytes.

    Allocate:5: 64Bytes.

    5: 0Bytes.

    Allocate:6: 0Bytes.

    6: 0Bytes.

    Allocate:7: 80Bytes.

    7: 0Bytes.

    Allocate:8: 88Bytes.

    8: 0 Bytes.

    Allocate:9: 96 Bytes.

    9: 0 Bytes.

    Allocate:10: 104 Bytes.

    10: 0 Bytes.

    Allocate:11: 0 Bytes.

    11: 0 Bytes.

    Allocate:12: 120 Bytes.

    12: 0 Bytes.

    Allocate:13: 128 Bytes.

    13: 0 Bytes.

    ……

    30: 0 Bytes.

    Allocate:31: 272 Bytes.

    31: 0 Bytes.

    Allocate:32: 280Bytes.

    32: -280 Bytes.

    Allocate:33: 288Bytes.

    33: -288Bytes.

    Allocate:34:296Bytes.

    34: -296Bytes.

    Allocate:35: 304 Bytes.

    35: -304 Bytes.

    Allocate:36: 312 Bytes.

    36: -312 Bytes.

    ……

    Allocate:98: 808 Bytes.

    98: -808 Bytes.

    Allocate:99: 816 Bytes.

    99: -816 Bytes.



    3.链接:http://blog.zol.com.cn/781/article_780182.html

    关于对象:

    如果两个对象之间存在着相互引用的关系,如“父对象-子对象”,对父对象调用 unset() 不会释放在子对象中引用父对象的内存(即便父对象被垃圾回收,也不行)。

    <?php
    class Foo {
    function __construct()
    {
    $this->bar = new Bar($this);
    }
    }
     
    class Bar {
    function __construct($foo = null)
    {
    $this->foo = $foo;
    }
    }
     
    while (true) {
    $foo = new Foo();
    unset($foo);
    echo number_format(memory_get_usage()) . "\n";
    }
    ?>
     

    运行这段代码,你会看到内存使用率越来越高越来越高,直到用光光。

    ...
    33,551,616
    33,551,976
    33,552,336
    33,552,696
    PHP Fatal error: Allowed memory size of 33554432 bytes exhausted
    (tried to allocate 16 bytes) in memleak.php on line 17

    虽然有些乏味、不优雅,但之前提到的 bugs.php.net 链接中提供了一个解决方案。

    这个方案在释放对象前使用一个 destructor 方法以达到目的。Destructor 方法可将所有内部的父对象引用全部清除,也就是说可以将这部分本来会溢出的内存释放掉。

    以下是“修复后”的代码:

    <?php
    class Foo {
    function __construct()
    {
    $this->bar = new Bar($this);
    }
    function __destruct()
    {
    unset($this->bar);
    }
    }
     
    class Bar {
    function __construct($foo = null)
    {
    $this->foo = $foo;
    }
    }
     
    while (true) {
    $foo = new Foo();
    $foo->__destruct();
    unset($foo);
    echo number_format(memory_get_usage()) . "\n";
    }
    ?>

    关于unset的总结:占用小内存的变量没有必要使用unset,使用了反而会更消耗内存,当变量占用内存>256Bytes时最好调用unset;使用php OOP时,一定要自定义析构函数。
  • 相关阅读:
    hbase与Hive的集成
    HBase API操作
    HBase原理
    HBase数据结构
    HBase Shell操作
    HBase简介
    Boxes in a Line
    B
    B. Painting Pebbles
    X
  • 原文地址:https://www.cnblogs.com/webu/p/3049913.html
Copyright © 2011-2022 走看看