Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:25831 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 56636 invoked by uid 1010); 26 Sep 2006 07:58:09 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 56621 invoked from network); 26 Sep 2006 07:58:09 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 26 Sep 2006 07:58:09 -0000 Authentication-Results: pb1.pair.com header.from=rquadling@googlemail.com; sender-id=pass; domainkeys=good Authentication-Results: pb1.pair.com smtp.mail=rquadling@googlemail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain googlemail.com designates 64.233.166.179 as permitted sender) DomainKey-Status: good X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: rquadling@googlemail.com X-Host-Fingerprint: 64.233.166.179 py-out-1112.google.com Linux 2.4/2.6 Received: from [64.233.166.179] ([64.233.166.179:48146] helo=py-out-1112.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 70/40-54386-E8DD8154 for ; Tue, 26 Sep 2006 03:58:08 -0400 Received: by py-out-1112.google.com with SMTP id c39so2627004pyd for ; Tue, 26 Sep 2006 00:58:04 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=googlemail.com; h=received:message-id:date:from:reply-to:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=FUr5hHQcRzMlNItiMMsP4q0J8lHMPybTWX+s6350o5PO3baacgon1/vO5XsEtKAFtDAz1LfZ2Wq1QGtfnsAfzT4aLZCaws0I5a5ygpV6llGoJ05uev7tHOF2sWLmMjItF7ZFk6yhEWofHJL49JhXPpgnr72TEDiNM2+EjGtHqkU= Received: by 10.35.89.10 with SMTP id r10mr294376pyl; Tue, 26 Sep 2006 00:51:20 -0700 (PDT) Received: by 10.35.93.18 with HTTP; Tue, 26 Sep 2006 00:51:14 -0700 (PDT) Message-ID: <10845a340609260051o35d63bb0s7ee57f117eb0f0db@mail.gmail.com> Date: Tue, 26 Sep 2006 08:51:14 +0100 Reply-To: RQuadling@GoogleMail.com To: "Jon Anderson" Cc: internals@lists.php.net In-Reply-To: <45183A84.3070307@gamingsolutions.ca> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <45183A84.3070307@gamingsolutions.ca> Subject: Re: [PHP-DEV] Object Memory Leakage... From: rquadling@googlemail.com ("Richard Quadling") On 25/09/06, Jon Anderson wrote: > I posted this to php-general several days ago, and the only response > suggested that perhaps I should forward the question to PHP internals. > If what's below isn't expected behavior, I'd be glad to dedicate a few > days to helping track down the problem. > > I've tried what's below on the server cluster in the office, running > Debian Sarge i386 (with an x86-64 kernel), PHP 5.0.16, and Apache > 2.0.54. I've also tried at home on a Gentoo box (Athlon-MPs) running PHP > 5.0.16 and Apache 2.2. Both produce similar results. (If > compiled-in/shared module lists, compile options, or any other > information would help, I can provide those too.) > > What's below this sentence is the original text of the message sent to > php-general. > > Sorry folks, this is a long one...I've re-read a bunch of the > documentation, and I can't find a solution. > > In debugging an out of memory condition, I found that PHP doesn't seem > to garbage collect unreferenced objects. It seems to work fine for > anything other than objects. (Arrays, strings, integers, etc.) > > Here's a simple example: define a class, create 3 instances, destroy > them in reverse order. I would expect that after each unset and/or NULL, > the memory usage would go down, they don't. See the output below. > > > class Tester { > protected $test1; > protected $test2; > protected $test3; > protected $test4; > > public function __construct() { > $test1 = rand(); > $test2 = rand(); > $test3 = rand(); > $test4 = rand(); > } > } > > echo memory_get_usage() . "\n"; > $t1 = new Tester(); > echo memory_get_usage() . "\n"; > $t2 = new Tester(); > echo memory_get_usage() . "\n"; > $t3 = new Tester(); > echo memory_get_usage() . "\n"; > unset($t3); > $t3 = NULL; > echo memory_get_usage() . "\n"; > $t2 = NULL; > echo memory_get_usage() . "\n"; > unset($t1); > echo memory_get_usage() . "\n"; > > > This outputs: > > 43344 > 43928 > 44232 > 44568 > 44640 > 44640 > 44640 > > Note: the memory usage remains constant after the objects are allocated, > even when they're unset/NULL'ed. > > Some of the user contributed notes on the PHP documentation suggest that > the memory is actually freed and available for use by other > variables/objects even though memory_get_usage() says otherwise. Another > little test seems to disprove that too... The idea here is to allocate > close to 8 MB, then free it to show that it can allocate that data > within the memory limit. Then allocate enough class instances and free > them again such that the memory usage increases enough that the same > data allocated and freed initially doesn't fit anymore. If PHP did > indeed free the objects, the data would fit the second time too... > > > ini_set('memory_limit','8m'); > > class Tester { > protected $test; > > public function __construct() { > $this->test = rand(); > } > } > > echo "Initial Memory Usage: " . memory_get_usage() . "\n"; > > $mb = 6 * 1024 * 1024; > echo "Allocating 7 MB of data..."; > $dat = ""; > for ($x=0;$x<$mb;$x++) { > $dat .= "x"; > } > echo "Memory Usage: " . memory_get_usage() . "\n"; > unset($dat,$x,$mb); > echo "Unset Usage: " . memory_get_usage() . "\n"; > > $num = 32767; > $objects = array(); > > echo "Initial Memory Usage (2): " . memory_get_usage() . "\n"; > echo "Allocating $num objects..."; > for ($x=0;$x<$num;$x++) { > $objects[$x] = new Tester(); > } > echo "Done. Memory Usage: " . memory_get_usage() . "\n"; > echo "Freeing $num objects..."; > for ($x=0;$x<$num;$x++) { > unset($objects[$x]); $objects[$x] = NULL; > } > echo "Done. Memory Usage: " . memory_get_usage() . "\n"; > > $mb = 6 * 1024 * 1024; > echo "Allocating 7 MB of data..."; > $dat = ""; > for ($x=0;$x<$mb;$x++) { > $dat .= "x"; > } > > This gives: > > Initial Memory Usage: 44248 > Allocating 7 MB of data...Memory Usage: 6335888 > Unset Usage: 44448 > Initial Memory Usage (2): 44504 > Allocating 32767 objects...Done. Memory Usage: 7752920 > Freeing 32767 objects...Done. Memory Usage: 2807080 > Allocating 7 MB of data... > Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to > allocate 1 bytes) in /home/janderson/svn/memtest.php on line 44 > > > Am I missing something? (Is there a force_garbage_collection() function > somewhere that I'm missing?) Any suggestions/workarounds/anything would > be most appreciated. > > Cheers, > > jon Using PHP 5.2.0RC5-dev (cli) (built: Sep 18 2006 08:20:52) on Windows (which has no memory_get_usage() functions), the scripts work fine. Allocating 7 MB of data...Allocating 32767 objects...Freeing 32767 objects...Allocating 7 MB of data... Using System Internals Process Explorer, you can see the memory increase and decrease as expected. Using the same script via ISAPI also worked as expected. Not much help in answering the issue, so maybe this is an issue that has been fixed already? -- ----- Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731 "Standing on the shoulders of some very clever giants!"