Bug #81585 [Opn]: Memory leaks when creating short string arrrays
| From: | cmb@php.net | Date: | Mon, 29 Nov 2021 17:53:28 +0000 |
| Subject: | Bug #81585 [Opn]: Memory leaks when creating short string arrrays | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-238043@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=81585&edit=1
ID: 81585
Updated by: cmb@php.net
Reported by: xtpd17 at gmail dot com
Summary: Memory leaks when creating short string arrrays
Status: Open
Type: Bug
-Package: Reproducible crash
+Package: Apache related
-Operating System: Windows 7 x64
+Operating System: Windows
-PHP Version: 8.0.12
+PHP Version: 7.4
-Assigned To:
+Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
First, the fact that not all request memory is freed on shutdown,
is a deliberate design decisions[1]. The reasoning is that later
reallocation of the memory from the OS is expensive.
Second, the total amount of memory allocated (httpd_mb) can easily
exceed PHP's memory_limit for a multi-threaded environment such as
Apache mpm_winnt. If I set
ThreadsPerChild 1 (note there is only
one child for mpm_winnt), I still get four threads (might be a
hard coded limit). Then the maximum amount of memory allocated is
about four times the memory_limit, so this doesn't look like a
bug. However, the reported values for memory_get_usage() are not
what I would have expected; it seems that memory_get_usage(true)
reports the per thread values, but memory_get_usage(false) return
the process values. I'll have a closer look.
[1] <https://github.com/php/php-src/blob/php-7.4.26/Zend/zend_alloc.c#L2264>
Previous Comments:
------------------------------------------------------------------------
[2021-11-01 19:59:52] xtpd17 at gmail dot com
Description:
------------
(System: Win7x64, last Apache 2.4 x32, php x32)
If your script creates array of small strings (not more than 2mb approx.) and gets all amount of
available memory (memory_limit could be set or left "-1") and then stops on "Fatal
error: Allowed memory exhausted", it doesn't free all memory, so size of httpd.exe remains
huge. If you run this script several times, size of httpd.exe grows and grows, and at some point
your _another_ "innocent" scripts fails when trying to alloc relatively small chunk of
memory with "Out of memory" (though their limits were not exceeded).
Steps to reproduce: reload script in browser several times until it fails. You'll see growing
initial size of httpd, then fail.
Notable things:
- memory leaks only when we create small string (<2mb)
- big (or not set) memory_limit spends memory faster
- it looks like E_USER_ERROR also keeps memory busy (see commented strings in script)
- at second run memory_get_usage(true) is close to zero, memory_get_usage() grows.
- in fact we have "out of memory" error already in the second run, but I thought it would
be more clear to have separate block to demonstrate leak.
- feel free to experiment with settings values in script.
TEST RESULTS (memory_limit = 1500M):
FIRST RUN ----------------------
apache size: 16 mb, memory usage/real usage: 0/2 mb (0 items in array, 0 mb stored)
apache size: 115 mb, memory usage/real usage: 98/100 mb (49 items in array, 98 mb stored)
apache size: 213 mb, memory usage/real usage: 196/198 mb (98 items in array, 196 mb stored)
...
Fatal error: Allowed memory size of 1572864000 bytes exhausted (tried to allocate 2093056 bytes) in
test_leak.php on line 58
before crash:
apache size: 1517 mb, memory usage/real usage: 1495/1500 mb (749 items in array, 1494 mb stored)
--- SECOND RUN ------------------------------
apache size: 766 mb, memory usage/real usage: 0/2 mb (0 items in array, 0 mb stored)
apache size: 766 mb, memory usage/real usage: 98/2 mb (49 items in array, 98 mb stored)
apache size: 766 mb, memory usage/real usage: 196/2 mb (98 items in array, 196 mb stored)
///
Fatal error: Out of memory (allocated 1113587712) (tried to allocate 2093056 bytes) in test_leak.php
on line 58
(WE HAVE OUT OF MEMORY ERROR ALREADY AT THIS POINT)
before crash:
apache size: 1828 mb, memory usage/real usage: 1805/1062 mb (904 items in array, 1804 mb stored)
--- THEN YOU GET 1297 mb of apache, then 1562...
--- AND THEN... FAIL RUN -------------------------------------
apache size: 1694 mb, memory usage/real usage: 0/2 mb (0 items in array, 0 mb stored)
apache overloaded (1694 mb), trying to alloc 200 mb
Fatal error: Out of memory (allocated 2097152) (tried to allocate 209715224 bytes) in test_leak.php
on line 51
before crash:
apache size: 1694 mb, memory usage/real usage: 0/2 mb (0 items in array, 0 mb stored)
Test script:
---------------
https://pastebin.com/qh8hneTg
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=81585&edit=1