1
1
Zend Memory Manager
2
2
===================
3
3
4
- Zend Memory Manager, often abbreviated as ZendMM or ZMM, is a C layer that aims to provide abilities to allocate and
5
- release dynamic **request-bound ** memory.
4
+ Zend Memory Manager, often abbreviated as * ZendMM * or * ZMM * , is a C layer that aims to provide abilities to allocate
5
+ and release dynamic **request-bound ** memory.
6
6
7
7
Note the "request-bound" in the above sentence.
8
8
@@ -18,7 +18,7 @@ PHP is a share-nothing architecture. Well, not at 100%. Let us explain.
18
18
here, you'll get additionnal informations about the different steps and cycles that can be drawn from PHP
19
19
lifetime.
20
20
21
- PHP can treat several (dozen, thousands?) of requests into the same process. By default, PHP will forget anything it
21
+ PHP can treat several hundreds or thousands of requests into the same process. By default, PHP will forget anything it
22
22
knows of the current request, when that later finishes.
23
23
24
24
"Forgetting" things translates to freeing any dynamic buffer that got allocated while treating a request. That means
@@ -35,7 +35,7 @@ default, PHP forgets *a very huge number* of informations from one request to an
35
35
36
36
There exists however some pretty rare informations you need to persist across several requests. But that's uncommon.
37
37
38
- What could be kept unchanged through requests? What we call **persistent ** objects. Once more let us insist : those
38
+ What could be kept unchanged through requests ? What we call **persistent ** objects. Once more let us insist : those
39
39
are rare cases. For example, the current PHP executable path won't change from requests to requests. That latter
40
40
information is allocated permanently, that means it is allocated with a traditionnal libc's ``malloc() `` call.
41
41
@@ -45,19 +45,19 @@ be allocated once.
45
45
46
46
What you must remember:
47
47
48
- * There exists two kinds of dynamic memory allocations while programming PHP ( or extensions) :
48
+ * There exists two kinds of dynamic memory allocations while programming PHP Core or extensions:
49
49
* Request-bound dynamic allocations.
50
50
* Permanent dynamic allocations.
51
51
52
52
* Request-bound dynamic memory allocations
53
53
* Must only be performed when PHP is treating a request (not before, nor after).
54
- * Can only be performed using the ZendMM dynamic memory allocation API.
55
- * Are very common, basically 95% of your dynamic allocations will be request-bound.
56
- * Are tracked by ZendMM, and you'll be informed about bad usage of the memory area, or if you leak .
54
+ * Should only be performed using the ZendMM dynamic memory allocation API.
55
+ * Are very common in extensions design , basically 95% of your dynamic allocations will be request-bound.
56
+ * Are tracked by ZendMM, and you'll be informed about leaking .
57
57
58
58
* Permanent dynamic memory allocations
59
59
* Should not be performed while PHP is treating a request (not forbidden, but a bad idea).
60
- * Are not tracked by ZendMM, and you won't be informed about bad usage of the memory area, or if you leak .
60
+ * Are not tracked by ZendMM, and you won't be informed about leaking .
61
61
* Should be pretty rare in an extension.
62
62
63
63
Also, keep in mind that all PHP source code has been based on such a memory level. Thus, many internal structures get
@@ -82,8 +82,8 @@ Persistent allocated one::
82
82
zend_array ar;
83
83
zend_hash_init(&ar, 8, NULL, NULL, 1);
84
84
85
- It is always the same in all the different Zend APIs. Usually, it is weither a "0" to pass as last parameter to mean
86
- "I want this structure to be allocated using ZendMM, so request-bound", or "1" meaning "I want this structure to get
85
+ It is always the same in all the different Zend APIs. Usually, it is whether a * "0" * to pass as last parameter to mean
86
+ "I want this structure to be allocated using ZendMM, so request-bound", or * "1" * meaning "I want this structure to get
87
87
allocated bypassing ZendMM and using a traditionnal libc's ``malloc() `` call".
88
88
89
89
Obviously, those structures provide an API that remembers how it did allocate the structure, to use the right
@@ -127,17 +127,17 @@ Whatever happens, pointers returned by ZendMM must be freed using ZendMM, aka ``
127
127
.. note :: A note on persistent allocations. Persistent allocations stay alive between requests. You traditionnaly use
128
128
the common libc ``malloc/free `` to perform that, but ZendMM has got some shortcuts to libc allocator : the
129
129
"persistent" API. This API starts by the *"p" * letter and let you choose between ZendMM alloc, or persistent
130
- alloc. Hence a ``pemalloc(<size> , 1) `` is nothing more than a ``malloc() ``, a ``pefree(<ptr> , 1) `` is a
131
- ``free() `` and a ``pestrdup(<ptr> , 1) `` is a ``strdup() ``. Just to say.
130
+ alloc. Hence a ``pemalloc(size_t , 1) `` is nothing more than a ``malloc() ``, a ``pefree(void * , 1) `` is a
131
+ ``free() `` and a ``pestrdup(void * , 1) `` is a ``strdup() ``. Just to say.
132
132
133
133
Zend Memory Manager debugging shields
134
134
*************************************
135
135
136
136
ZendMM provides the following abilities:
137
137
138
138
* Memory consumption management.
139
- * Memory leak tracking.
140
- * Buffer overflows or underflows.
139
+ * Memory leak tracking and automatic-free .
140
+ * Speed up in allocations by pre-allocating well-known-sized buffers and keeping a warm cache on free
141
141
142
142
Memory consumption management
143
143
-----------------------------
@@ -183,7 +183,7 @@ If you forget to free blocks, they will all get displayed on *stderr*. This proc
183
183
in the following conditions:
184
184
185
185
* You are using :doc: `a debug build<../build_system/building_php> ` of PHP
186
- * You have report_memleaks=On in php.ini (default)
186
+ * You have * report_memleaks=On * in php.ini (default)
187
187
188
188
Here is an example of a simple leak into an extension::
189
189
@@ -206,14 +206,21 @@ Beware however:
206
206
than using it. Hence, ZendMM can only warn you about allocations it is aware of, every traditionnal libc allocation
207
207
won't be reported in here, f.e.
208
208
* If PHP shuts down in an incorrect maner (what we call an unclean shutdown), ZendMM will report tons of leaks. This is
209
- because when incorrectly shutdown, the engine uses a longjmp() call to a catch block, preventing every code that cleans
210
- memory to fire-in. Thus, many leaks get reported. This happens especially after a call to PHP's exit()/die(), or if a
211
- fatal error gets triggered in some critical parts of PHP.
212
- * If you use a non-debug build of PHP, nothing shows on stderr, ZendMM is dumb.
209
+ because when incorrectly shutdown, the engine uses a
210
+ `longjmp() <http://man7.org/linux/man-pages/man3/longjmp.3.html >`_ call to a catch block, preventing every code that
211
+ cleans memory to fire-in. Thus, many leaks get reported. This happens especially after a call to PHP's exit()/die(),
212
+ or if a fatal error gets triggered in some critical parts of PHP.
213
+ * If you use a non-debug build of PHP, nothing shows on *stderr *, ZendMM is dumb but will still clean any allocated
214
+ request-bound buffer that's not been explicitely freed by the programmer
213
215
214
216
What you must remember is that ZendMM leak tracking is a nice bonus tool to have, but it does not replace a
215
217
:doc: `true C memory debugger <./memory_debugging >`.
216
218
219
+ ZendMM internal design
220
+ **********************
221
+
222
+ .. todo :: todo
223
+
217
224
Common errors and mistakes
218
225
**************************
219
226
0 commit comments