Resolves whether or not unset in PHP frees memory

  • 2020-07-21 07:17:57
  • OfStack

Let's start with an example


    var_dump(memory_get_usage());
    $a = "laruence";
    var_dump(memory_get_usage());
    unset($a);
    var_dump(memory_get_usage());

Output (on my PC, this may vary depending on the extensions that the system,PHP version, loads):
int(90440)
int(90640)
int(90472

Noting that 90472-90440=32, various conclusions are drawn. Some people say that PHP's unset does not really free memory, others say that unset of PHP only releases large variables (lots of strings, large arrays), and still others say that it is meaningless to talk about memory at the level of PHP.

So, will unset free up memory at all? Where did those 32 bytes go?
To answer this question, I will start from two aspects:
Where do these 32 bytes go

The first thing to think about is that unlike THE C language, PHP only has memory allocation if you show it to be related to the call memory allocation.
That said, in PHP, there are a lot of memory allocation processes that we don't see.
For example, for:


    $a = "laruence";

The implicit memory allocation points are:
1. Allocate memory for variable name and store it in symbol table
2. Assign the value of the variable

So you can't just look at appearances.
Second, don't doubt that unset of PHP does free memory (with reference and counting, of course, see my previous article for an in-depth understanding of the PHP principle of variable separation/reference), but this release is not a release in the programming sense of C and is not returned to OS.
For PHP, it itself provides a set of memory management API that is similar to the C language for memory allocation. These API correspond to the API meaning of C and are used to manage memory within PHP.

When we call emalloc to apply for memory, PHP does not simply ask for memory from OS, but asks for a large block of memory like OS, and then allocates one block to the applicant. In this way, when there is logic to apply for memory, it is no longer necessary to apply for memory from OS, avoiding frequent system calls.
Take the following example:

    <?php
    var_dump(memory_get_usage(TRUE)); // Notice what I'm getting real_size
    $a = "laruence";
    var_dump(memory_get_usage(TRUE));
    unset($a);
    var_dump(memory_get_usage(TRUE));

Output:
int(262144)
int(262144)
int(262144

When we defined the variable $a, PHP did not request new memory from the system.

Similarly, when we call efree free memory, will not return the memory to OS PHP, and take this piece of memory, in their list of free memory maintenance. For small pieces of memory, more likely, to put it in the memory cache list (PHP epilogue, some versions, such as I verified PHP5. 2.4, 5.2.6, 5.2.8, in the call get_memory_usage (), The size of the available memory block in the memory cache list is not subtracted, resulting in the memory appearing unchanged after unset.

Now let me answer the question of where those 32 bytes go. As I said, a lot of memory allocation is not explicit, as you can see by looking at the following code:


    <?php
    var_dump("I am www.ofstack.com");
    var_dump(memory_get_usage());
    $a = "laruence";
    var_dump(memory_get_usage());
    unset($a);
    var_dump(memory_get_usage());

Output:
string(43) "I am www.ofstack.com"
int(90808) // Before assignment
int(90976)
int(90808) // Yes, memory is released normally

90808-90808 = 0, ok, so 32 bytes are occupied by the output function (strictly speaking, Header)

An array that just keeps growing
Hashtable is the core structure of PHP (for more information on Hashtable, see my previous article for an in-depth understanding of PHP's array (traversal order)). The array is also represented by PHP, and the symbol table is also an associative array, for the following code:


    var_dump("I am www.ofstack.com");
    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());

We defined 100 variables, and then pressed Unset to see the output:
string(43) "I am www.ofstack.com"
int(93560)
int(118848)
int(104448

Wow, why is there so much memory missing?
This is because when defining Hashtable, it is impossible to allocate enough blocks once to hold an unknown number of elements, so PHP will only allocate 1 small block of memory to HashTable at initialization time, and then expand RESIZE when it is not enough.

And Hashtable, can only increase, not decrease, in the above example, when we are in 100 variables, the symbol table not enough use, made one expands, and when we, in turn, unset off after the 100 variable, the variable memory is released (118848 � 104448), but the symbol table, does not seem to be shrinking, so the less memory is the symbol table itself takes up...

Now, do you have a basic understanding of PHP's memory management?


Related articles: