Viewed   175 times

Running PHP 5.3.6 under MAMP on MAC, the memory usage increases every x calls (between 3 and 8) until the script dies from memory exhaustion. How do I fix this?

libxml_use_internal_errors(true);
while(true){
 $dom = new DOMDocument();
 $dom->loadHTML(file_get_contents('http://www.ebay.com/'));
 unset($dom);
 echo memory_get_peak_usage(true) . '<br>'; flush();
}

 Answers

5

Using libxml_use_internal_errors(true); suppresses error output but builds a continuous log of errors which is appended to on each loop. Either disable the internal logging and suppress PHP warnings, or clear the internal log on each loop iteration like this:

<?php
libxml_use_internal_errors(true);
while(true){
 $dom = new DOMDocument();
 $dom->loadHTML(file_get_contents('ebay.html'));
 unset($dom);
 libxml_use_internal_errors(false);
 libxml_use_internal_errors(true);
 echo memory_get_peak_usage(true) . "rn"; flush();
}
?>
Sunday, August 21, 2022
2

PHP 5.3 has a garbage collector that can collect cyclic references. It might be worth it to try:

gc_enable();

class A {
  public function __construct() {
    $this->data = str_repeat("A", 1024000);
  }
}

$mem = memory_get_usage();
$a = new A();
$mem2 = memory_get_usage();
$a->a = $a;
$a->a->mydata =  $a->data . 'test';
$mem3 = memory_get_usage();
unset($a);
gc_collect_cycles();
$mem4 = memory_get_usage();      

printf("MEM 1 at start %0.2f Mbn", ($mem / 1024) / 1024);
printf("MEM 2 after first instantiation %0.2f Mbn", ($mem2 / 1024) / 1024);
printf("MEM 3 after self-ref: %0.2f Mbn", ($mem3 / 1024) / 1024);
printf("MEM 4 after unset($a): %0.2f Mbn", ($mem4 / 1024) / 1024);      

Output:

MEM 1 at start: 0.31 Mb
MEM 2 after first instantiation: 1.29 Mb
MEM 3 after self-ref: 2.26 Mb
MEM 4 after unset($a): 0.31 Mb   
Saturday, December 17, 2022
4

This is actually not a memory leak, but rather static function caches that aren't being cleaned!

This is due to SimplePie_IRI::set_iri (and set_authority, and set_path). They set a static $cache variable, but they don't unset or clean this when a new instance of SimplePie is created, which means the variables only gets bigger and bigger.

This can be fixed by changing

public function set_authority($authority)
{
    static $cache;

    if (!$cache)
        $cache = array();

    /* etc */

to

public function set_authority($authority, $clear_cache = false)
{
    static $cache;
    if ($clear_cache) {
        $cache = null;
        return;
    }

    if (!$cache)
        $cache = array();

    /* etc */

..etc in the following functions:

  • set_iri,
  • set_authority,
  • set_path,

And adding a destructor to SimplePie_IRI calling all the functions using a static cache, with a parameter of true in $clear_cache, will work:

/**
 * Clean up
 */
public function __destruct() {
    $this->set_iri(null, true);
    $this->set_path(null, true);
    $this->set_authority(null, true);
}

Which will now result in no gain in memory consumption over time:

Git Issue

Tuesday, November 29, 2022
 
jtdubs
 
4

In Xcode 8, you can click on the "Debug Memory Graph" button, in the debug toolbar (shown at the bottom of the screen):

Just identify the object in the left panel that you think should have been deallocated, and it will show you the object graph (shown in the main canvas, above). This is very useful in quickly identifying where the strong references were established on the object in question. From here, you can start your research, diagnosing why those strong references were not resolved (e.g. if the object in question has a strong reference from something else that should have been deallocated, look at that object's graph, too, and you may find the issue (e.g. strong reference cycles, repeating timers, etc.).

Notice, that in the right panel, I'm seeing the call tree. I got that by turning on the "malloc stack" logging option in the scheme settings:

Anyway, having done that, one can then click on the arrow next to the relevant method call shown in the stack trace in the right panel of the first screen snapshot above, and you can see where that strong reference was originally established:

The above memory diagnostic technique (and more) is demonstrated in the latter part of WWDC 2016 Visual Debugging with Xcode.


The traditional Instruments technique (especially useful if using older versions of Xcode) is described below, in my original answer.


I would suggest using Instruments' "Allocations" tool with the "Record Reference Counts" feature:

You can then run the app in Instruments and then search for your class that you know is leaking and drill in by clicking on the arrow:

You can then drill into the details and look at the stack trace using the "Extended Details" panel on the right:

In that "Extended Details" panel, focus on your code in black rather than the system calls in gray. Anyway, from the "Extended Details" panel, you can then drill into your source code, right in Instruments::

For more information and demonstrations in using Instruments to track down memory problems, please refer to:

  • WWDC 2013 video Fixing Memory Issues
  • WWDC 2012 video iOS App Performance: Memory
Tuesday, December 27, 2022
 
herbn
 
14

Use the display-name option as documented in mod_wsgi documentation to label the mod_wsgi daemon processes. That way you can see with 'ps' if the large processes are in fact the mod_wsgi daemon processes.

http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIDaemonProcess

If they are quite fat, then Apache or mod_wsgi isn't anything to do with it. It is going to be because your applications are themselves fat. This may be because of excessive caching of data in memory or resource leakage.

If the labelled mod_wsgi daemon mode processes aren't fat, then you may have not delegated the Python applications to run in the daemon processes properly. That or your PHP application is the problem.

http://code.google.com/p/modwsgi/wiki/CheckingYourInstallation#Embedded_Or_Daemon_Mode

In short, when your application is fat, it isn't going to matter what hosting mechanism you use, they will still be fat and Apache and mod_wsgi have got nothing to do with it unless you have stuffed up the Apache configuration.

Friday, August 5, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :