Bug #79518 [Opn->Fbk]: SimpleXML memory leak

From: Date: Tue, 17 Nov 2020 12:44:37 +0000
Subject: Bug #79518 [Opn->Fbk]: SimpleXML memory leak
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-230405@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79518&edit=1

 ID:                 79518
 Updated by:         cmb@php.net
 Reported by:        ivo at beerntea dot com
 Summary:            SimpleXML memory leak
-Status:             Open
+Status:             Feedback
 Type:               Bug
 Package:            SimpleXML related
 Operating System:   Linux
 PHP Version:        7.3.17
-Assigned To:        
+Assigned To:        cmb
 Block user comment: N
 Private report:     N

 New Comment:

> In addition the XML DOM appeard to use significantly more memory
> than the original XML string, […]

What is not unexpected, given that the DOM is stored as a tree
structure, with a lot of info for each node.  That would be a
libxml issue, though.

> , and the memory used by the XML DOM is not accounted for by PHP
> (see #63380), allowing to bypass the PHP memory limit.

Besides that already tracked in the other bug report, it is not
likely something we can fix without further support from libxml.

> The memory used by the XML functions remains in use even when
> there are no more references:

Are you sure?  This may be just the ZendMM optimization which does
not immediately give all possible memory back to the OS, to avoid
unnecessary re-allocations for the next request.  To check that,
you can run the script(s) with USE_ZEND_ALLOC=0.


Previous Comments:
------------------------------------------------------------------------
[2020-04-24 10:35:27] ivo at beerntea dot com

Description:
------------
SimpleXML and DOMDocument (and possibly other libxml functions) do not always free the allocated
memory after all references to the XML/DOM object have been released.

This especially is a problem in environments where the same process is used to handle multiple
requests, like the FPM interface, as memory allocated by one script won't be released until the
FPM process is terminated. When handling large XML files this can easily push a server out of
memory.

In addition the XML DOM appeard to use significantly more memory than the original XML string, and
the memory used by the XML DOM is not accounted for by PHP (see #63380), allowing to bypass the PHP
memory limit.

PHP version: 7.3.17-1+ubuntu18.04.1+deb.sury.org+1
Linux kernel 4.15.0-91-generic x86_64

Test script:
---------------
<?php
function mstat() {
  //Print reserved memory according to PHP and total mapped memory according to OS (assumes 4k page
size and Linux) 
  $statm = explode(' ', file_get_contents('/proc/self/statm'));
  printf("PHP memory usage=%u MB, process memory usage=%u MB\n", memory_get_usage(TRUE) /
1024 / 1024, $statm[0] * 4096 / 1024 / 1024);
}

mstat();

$xml = '<doc>'.str_repeat('<node
attr="attr">test</node>', 1000000).'</doc>';
printf("Preparing big XML: %u MB.\n", strlen($xml) / 1024 / 1024);
mstat();

$flags = 0;
$flags |= LIBXML_COMPACT; //COMPACT flag reduces memory usage a little bit, not much

echo "Parsing DOM document without storing reference...\n";
(new \DOMDocument())->loadXML($xml, $flags);
mstat();

echo "Parse XML DOM without storing reference...\n";
simplexml_load_string($xml, 'SimpleXMLElement', $flags);  
mstat();

echo "Parse XML DOM without storing reference...\n";
simplexml_load_string($xml, 'SimpleXMLElement', $flags);  
mstat();

echo "Parse XML DOM storing reference...\n";
$dom = simplexml_load_string($xml, 'SimpleXMLElement', $flags);  
mstat();

echo "Parse XML DOM overwriting reference...\n";
$dom = simplexml_load_string($xml, 'SimpleXMLElement', $flags);  
mstat();

echo "Unset XML string...\n";
$xml = NULL;
mstat();

echo "Unset DOM references...\n";
$dom = $dom2 = $dom3 = NULL;
mstat();

Expected result:
----------------
Indicated memory usage should return back to the initial value after a reference to the XML/DOM
object is cleared.

Actual result:
--------------
The memory used by the XML functions remains in use even when there are no more references:

PHP memory usage=2 MB, process memory usage=391 MB
Preparing big XML: 27 MB.
PHP memory usage=29 MB, process memory usage=419 MB
Parsing DOM document without storing reference...
PHP memory usage=29 MB, process memory usage=892 MB



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=79518&edit=1


Thread (8 messages)

« previous php.bugs (#230405) next »