Asked  7 Months ago    Answers:  5   Viewed   55 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

86

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();
}
?>
Wednesday, March 31, 2021
 
millenomi
answered 7 Months ago
42

Version 5.1.6 of PHP seems to have an issue with memory leaking when using "CURLOPT_RETURNTRANSFER, true" to store the results of the cURL as a string. Upgrading to 5.3 sorted the leak out for me.

Thanks

Wednesday, March 31, 2021
 
Bharanikumar
answered 7 Months ago
96

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   
Wednesday, March 31, 2021
 
hillz
answered 7 Months ago
36

I got the same problem. Maybe the best idea is to report new bug at PEAR

BTW, code like that doesn't show that memleak:

#!/usr/bin/php -q

<?php
require_once "System/Daemon.php";
System_Daemon::setOption("appName", "smsd");
System_Daemon::start();
while(!System_Daemon::isDying()) {
 print ("debug: memory_get_peak_usage: ".memory_get_peak_usage()."n");
 print ("debug: memory_get_usage: ".memory_get_usage()."nn");
 System_Daemon::iterate(2);

}

Look's like System_Daemon::info() is a problem.

Saturday, May 29, 2021
 
osondoar
answered 5 Months ago
75

If the adapter lives any longer than the RecyclerView does, you've got to clear the adapter reference in onDestroyView:

@Override
public void onDestroyView() {
    recyclerView.setAdapter(null);
    super.onDestroyView();
}

Otherwise the adapter is going to hold a reference to the RecyclerView which should have already gone out of memory.

If the screen is involved in transition animations, you actually have to take this one step further and only clear the adapter when the view has become detached:

@Override
public void onDestroyView() {
    recyclerView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
        @Override
        public void onViewAttachedToWindow(View v) {
            // no-op
        }

        @Override
        public void onViewDetachedFromWindow(View v) {
            recyclerView.setAdapter(null);
        }
    });
    super.onDestroyView();
}
Saturday, September 4, 2021
 
Optimight
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :