PHP memory overflow Allowedmemorysizeof solution

Source: Internet
Author: User
PHP memory overflow Allowedmemorysizeof solution ============================ Allowedmemorysizeof? Xxxbytes? I have tracked this problem before, but at that time the tool was not used very well. I didn't see it so carefully. this time I made a little detail and corrected my previous views. so write a small PHP memory overflow Allowed memory size of solution


======================================Allowed memory size? Xxx bytes

?

I have tracked this problem before, but at that time the tool was not used very well. I didn't see it so fine. this time I made a little detail and corrected my previous views.

So I wrote a summary of this article.

The following error Allowed memory size? Xxx bytes exhausted at xxx: xxx (tried

Allocate xxx bytes)

If you don't want to look at the principle, jump to the end to see the summary.

This error message indicates that if the memory limit configured by ini is greater than AG (allocated_memory), an error is returned.

?

?

AG (allocated_memory) + = rs;
?
If (AG (memory_limit )?
??? Int php_mem_limit = AG (memory_limit );
??? AG (allocated_memory)-= rs;
?
?? If (EG (in_execution) & AG (memory_limit) + 1048576> AG (allocated_memory )){
?
??????? AG (memory_limit) = AG (allocated_memory) + 1048576;
?
??????? If (file ){
??????????? Zend_error (E_ERROR, "Allowed memory size of % d bytes exhausted
At % s: % d (tried to allocate % d bytes) ", php_mem_limit, file, lineno, s );
??????? } Else {
??????????? Zend_error (E_ERROR, "Allowed memory size of % d bytes exhausted
(Tried to allocate % d bytes) ", php_mem_limit, s );
??????? }
?
??? } Else {
?
??????? If (file ){
?????????? Fprintf (stderr, "Allowed memory size of % d bytes exhausted
At % s: % d (tried to allocate % d bytes) n ", php_mem_limit, file, lineno, s );
??????? } Else {
??????????? Fprintf (stderr, "Allowed memory size of % d bytes exhausted
(Tried to allocate % d bytes) n ", php_mem_limit, s );
??????? }
?
??????? Exit (1 );
??? }
}


Memory_limit is simple, that is, what is the memory. AG (allocated_memory) available for PHP? Is the memory used? well,

Let's verify it with code.

PHP_FUNCTION (memory_get_usage ){
??????? RETURN_LONG (AG (allocated_memory ));
}
This is clear. if you still don't understand it, check the php manual and read the description of memory_get_usage.

When can I set AG (allocated_memory)? the specific code is not pasted, which is too cumbersome. it is called in the first section of the emalloc function.

Code, look at the first line of code, where the rs is the s variable corresponding to each tried to allocate % d bytes (the actual space you want to apply)

Align )&~ 0x7, that is, it must be a multiple of 8. if it is not enough, it must be supplemented.

64-bit machine requirements can accelerate the operation, such as s = 1, then the calculated rs = 8, specific, you can write a function compute using PHP

(0 × 7 is written in hexadecimal notation ).

Conclusion: now that you know what is going on, you can solve the problem. when you enable-memory-limit, this error occurs.

Directly set memory_limit, or set ini_set ('memory _ limit ', 'value') in the code.

Is to set the configuration file (such as php. ini)

In addition, we recommend that you enable-memory-limit. if this option is not enabled, the PHP memory limit will be in the "bare run" status, which may result in

Out of memory error.


One of the biggest advantages of using a scripting language is that it can use its automatic garbage collection mechanism (releasing memory ). You do not need to change it after use

PHP will help you do any processing to release the memory.

Of course, we can call the unset () function as needed to release the memory, but this is usually not required.

?

However, in PHP, memory is not automatically released in at least one case, even when unset () is called manually (). Details are available:

Http://bugs.php.net/bug.php? Id = 33595.

Symptom
If there is a mutual reference relationship between the two objects, such as "parent object-sub-object", the call of unset () to the parent object will not be released in the child object

The memory of the parent object referenced in the object (even if the parent object is recycled by garbage collection ).

Are you confused? Let's take a look at the following code:

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 ";
}
?>
? Run this code and you will see that the memory usage is getting higher and higher until the light is used up.

...
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
? This is not a problem for most PHP programmers.

However, if you use a lot of referenced objects in a long-running code, especially when the object is relatively large

Storage will quickly consume up.

?

Userland solution
Although tedious and not elegant, a solution is provided in the previously mentioned bugs.php.net link.

This solution uses a destructor method before releasing an object to achieve the goal. The Destructor method can set all internal parent objects

Clear all references. that is to say, you can release the memory that will be overflows.

The following is the "fixed" code:

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 ";
}
?>
? Note the newly added Foo ::__ destruct () method and call $ foo->__ destruct () before releasing the object. Now

The code segment solves the problem of increasing memory usage, so that the code can work well.

PHP kernel solution?
Why is memory overflow? I am not proficient in PHP kernel research, but it is certain that this problem is related to reference count.

System.

The reference count for referencing $ foo in $ bar will not decrease because the parent object $ foo is released. PHP thinks that you still need $ foo

Will not release this part of memory ...... This is probably the case.

It can be seen that I am ignorant, but it generally means that the reference count is not decreasing, so some memory will never be released.

?

In the above-mentioned bugs.php.net link, I can see that the process of modifying garbage collection will sacrifice a lot of performance, because I am counting references.

I don't know much about it, so I think it's true.

?

Instead of changing the garbage collection process, why don't unset () be used to release internal objects? (Or when the object is released

Call _ destruct ()?)

Maybe PHP kernel developers can modify this garbage collection mechanism here or elsewhere.

?

Update: Martin Fjordvald mentioned a patch written by David Wang for garbage collection (in fact, it looks more

Like "a whole cloth"-very huge. For details, see the CVS export information at the end of this email .) Does exist (an email) and receives

Followed by PHP kernel developers. The problem is that this patch does not get much support in PHP5.3. I think it's good.

The compromise is to call the _ destruct () method in the object in the unset () function;

?

?

?

?

======================================Memory overflow solution

?

During data statistical analysis, large arrays are often encountered, and memory overflow may occur. here is my solution. The problem is illustrated in the following example:

Assume that the number of records in the log is 500000, the solution is as follows:

?

Ini_set ('memory _ limit ', '64m'); // reset the memory size that php can use to 64 MB. generally, php cannot be modified on a remote host. the INI file can only be set through the program. Note: ini_set is invalid in safe_mode (security mode ).

Set_time_limit (600); // Set the timeout limit to 6 minutes.

?

$ Farr? =? $ Uarr? =? $ Marr? =? $ IParr? =? $ Data? =? $ _ Sub ?? =? Array ();

$ Spt? = ?" $ @#! $ ";

$ Root? = ?" /Data/webapps/VisitLog ";

$ Path? =? $ Dpath? =? $ Fpath? =? NULL;

$ Path? =? $ Root. "/". date ("Y-m", $ timestamp );

$ Dpath? =? $ Path. "/". date ("m-d", $ timestamp );

For ($ j = 0; $ j <24; $ j ++ ){

$ V? =? ($ J?

$ Gpath? =? $ Dpath. "/". $ v. ". php ";

If (! File_exists ($ gpath )){

Continue;

}? Else? {

$ Arr? =? File ($ gpath); // read the file into the array

Array_shift ($ arr); // remove the first unit-"

$ Farr? =? Array_merge ($ farr, $ arr );

Unset ($ arr );

}

}

If (empty ($ this-> farr )){

Echo ?"

No related records!

";

Exit;

}

While (! Empty ($ farr )){

$ _ Sub? =? Array_splice ($ farr ,? 0 ,? 10000 );? // Retrieve 1000 of $ farr at a time

For ($ I = 0, $ scount = count ($ _ sub); $ I <$ scount; $ I ++ ){

$ Arr? =? Explode ($ spt, $ _ sub [$ I]);

$ Uarr []? =? $ Arr [1];? // Vurl

$ Marr []? =? $ Arr [2];? // Vmark

$ IParr []? =? $ Arr [3]. "? | $ Nbsp; ". $ arr [1];? // IP

}

Unset ($ _ sub); // destroy immediately after use

}

Unset ($ farr );

?

It is not difficult to see that, on the one hand, we wantAdd PHPAvailable memory sizeOn the other hand, we only need to find a solutionBatch processing of arrays, Divide and conquer, willTimely destruction of used variables (unset)Generally, there will be no overflow issues..

?

In addition, to save the memory consumption of PHP programs,We should minimize the use of static variables. when we need to re-use data, we can consider using references.(&). Another point is that the connection should be closed immediately after the database operation is completed. after an object is used up, the destructor (_ destruct () should be called in time ()).

?

?

?

?

======================================Unset: destroying variables and releasing memory

?

?


The unset () function of PHP is used to clear and destroy variables. unused variables can be destroyed using unset. However, in some cases, the memory occupied by the volume change cannot be destroyed with unset! Let's first look at an example:

$ S = str_repeat ('1', 255); // generates a string consisting of 255 1
$ M = memory_get_usage (); // Get the memory occupied currently
Unset ($ s );
$ Mm = memory_get_usage (); // unset () and check the memory occupied.
Echo $ m-$ mm;
?>

Finally, the output unset () occupies memory minus unset () and then occupies memory. if it is a positive number, it indicates that unset ($ s) has destroyed $ s from memory (or, after unset (), the memory usage is reduced. However, on the PHP5 and windows platforms, the result is: 0. Does this indicate that unset ($ s) does not play the role of destroying the memory occupied by the variable $ s? Let's take the following example:

$ S = str_repeat ('1', 256); // generates a string consisting of 256 1
$ M = memory_get_usage (); // Get the memory occupied currently
Unset ($ s );
$ Mm = memory_get_usage (); // unset () and check the memory occupied.
Echo $ m-$ mm;
?>

In this example, it is almost the same as the preceding example. The only difference is that $ s is composed of 256 1 s, that is, one more than the first example. The result is 272. Does this mean that unset ($ s) has destroyed the memory occupied by $ s?
Through the above two examples, we can draw the following conclusions:
Conclusion 1,The unset () function can only release memory space when the variable value occupies more than 256 bytes of memory.

Is it possible to use unset to release memory space as long as the variable value exceeds 256? Let's test it through an example:

$ S = str_repeat ('1', 256); // This is exactly the same as the second example.
$ P = & $ s;
$ M = memory_get_usage ();
Unset ($ s); // destroy $ s
$ Mm = memory_get_usage ();
Echo $ p .'
';
Echo $ m-$ mm;
?>

Refresh the page. we can see that there are 256 1 in the first line and 0 in the second line. we have destroyed $ s, and $ p is just a variable that references $ s, there should be no content. In addition, the memory usage before and after unset ($ s) remains unchanged! Now let's take the following example:

$ S = str_repeat ('1', 256); // This is exactly the same as the second example.
$ P = & $ s;
$ M = memory_get_usage ();
$ S = null; // Set $ s to null.
$ Mm = memory_get_usage ();
Echo $ p .'
';
Echo $ m-$ mm;
?>

Refresh the page and we can see that the output $ p has no content. The difference between memory usage and unset () is 272, that is, the memory occupied by variables has been cleared. In this example, $ s = null can also be replaced with unset (), as follows:

$ S = str_repeat ('1', 256); // This is exactly the same as the second example.
$ P = & $ s;
$ M = memory_get_usage ();
Unset ($ s); // destroy $ s
Unset ($ p );
$ Mm = memory_get_usage ();
Echo $ p .'
';
Echo $ m-$ mm;
?>

We will use unset () to destroy both $ s and $ p. then we can see that the memory usage difference is also 272, which means the memory can be released. Then, we can draw another conclusion:
Conclusion 2: OnlyMemory is released only when all variables pointing to this variable (such as referenced variables) are destroyed.

?

?

?

?

?

?

?

?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.