Skip to content

Commit f26c510

Browse files
observe ZendMM garbage collection
1 parent 7919627 commit f26c510

File tree

4 files changed

+62
-20
lines changed

4 files changed

+62
-20
lines changed

Zend/zend_alloc.c

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,21 @@ struct _zend_mm_observer {
203203
void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
204204
void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
205205
void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
206+
void (*gc)(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
206207
zend_mm_observer *next;
207208
};
208209

210+
#define HANDLE_OBSERVERS(heap, use_custom_heap, observer_function, ...) \
211+
if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \
212+
zend_mm_observer *current = heap->observers; \
213+
while (current != NULL) { \
214+
if (current->observer_function != NULL) { \
215+
current->observer_function(__VA_ARGS__ ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
216+
} \
217+
current = current->next; \
218+
} \
219+
}
220+
209221
/*
210222
* Memory is retrieved from OS by chunks of fixed size 2MB.
211223
* Inside chunk it's managed by pages of fixed size 4096B.
@@ -1966,7 +1978,9 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap)
19661978
size_t collected = 0;
19671979

19681980
#if ZEND_MM_CUSTOM
1969-
if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) {
1981+
int use_custom_heap = heap->use_custom_heap;
1982+
if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) {
1983+
HANDLE_OBSERVERS(heap, use_custom_heap, gc ,0);
19701984
return 0;
19711985
}
19721986
#endif
@@ -2065,6 +2079,10 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap)
20652079
}
20662080
} while (chunk != heap->main_chunk);
20672081

2082+
#if ZEND_MM_CUSTOM
2083+
HANDLE_OBSERVERS(heap, use_custom_heap, gc, collected * ZEND_MM_PAGE_SIZE);
2084+
#endif
2085+
20682086
return collected * ZEND_MM_PAGE_SIZE;
20692087
}
20702088

@@ -2494,17 +2512,6 @@ ZEND_API bool is_zend_ptr(const void *ptr)
24942512

24952513
#if ZEND_MM_CUSTOM
24962514

2497-
#define HANDLE_OBSERVERS(observer_function, ...) \
2498-
if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \
2499-
zend_mm_observer *current = heap->observers; \
2500-
while (current != NULL) { \
2501-
if (current->observer_function != NULL) { \
2502-
current->observer_function(__VA_ARGS__ ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2503-
} \
2504-
current = current->next; \
2505-
} \
2506-
}
2507-
25082515
static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
25092516
{
25102517
void *ptr;
@@ -2518,7 +2525,7 @@ static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_D
25182525
// no custom memory manager, only observer present
25192526
ptr = zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25202527
}
2521-
HANDLE_OBSERVERS(malloc, size, ptr)
2528+
HANDLE_OBSERVERS(heap, use_custom_heap, malloc, size, ptr)
25222529
return ptr;
25232530
}
25242531

@@ -2527,7 +2534,7 @@ static ZEND_COLD void ZEND_FASTCALL _efree_custom(void *ptr ZEND_FILE_LINE_DC ZE
25272534
zend_mm_heap *heap = AG(mm_heap);
25282535
int use_custom_heap = heap->use_custom_heap;
25292536

2530-
HANDLE_OBSERVERS(free, ptr)
2537+
HANDLE_OBSERVERS(heap, use_custom_heap, free, ptr)
25312538

25322539
if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) {
25332540
heap->custom_heap.debug._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
@@ -2552,7 +2559,7 @@ static ZEND_COLD void* ZEND_FASTCALL _realloc_custom(void *ptr, size_t size ZEND
25522559
// no custom memory manager, only observer present
25532560
new_ptr = zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25542561
}
2555-
HANDLE_OBSERVERS(realloc, ptr, size, new_ptr)
2562+
HANDLE_OBSERVERS(heap, use_custom_heap, realloc, ptr, size, new_ptr)
25562563
return new_ptr;
25572564
}
25582565
#endif
@@ -3091,7 +3098,8 @@ ZEND_API zend_mm_observer* zend_mm_observer_register(
30913098
zend_mm_heap* heap,
30923099
void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
30933100
void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
3094-
void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
3101+
void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
3102+
void (*gc)(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
30953103
) {
30963104
#if ZEND_MM_CUSTOM
30973105
if (!heap) {
@@ -3103,6 +3111,7 @@ ZEND_API zend_mm_observer* zend_mm_observer_register(
31033111
node->malloc = malloc;
31043112
node->free = free;
31053113
node->realloc = realloc;
3114+
node->gc = gc;
31063115
node->next = NULL;
31073116

31083117
// set bitflag for observers being around

Zend/zend_alloc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ ZEND_API zend_mm_observer* zend_mm_observer_register(
289289
zend_mm_heap *heap,
290290
void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
291291
void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
292-
void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
293-
292+
void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
293+
void (*gc)(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
294294
);
295295
ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *observer);
296296
void zend_mm_observers_shutdown(zend_mm_heap *heap);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
ZendMM Observer: Observe garbage collection
3+
--EXTENSIONS--
4+
zend_test
5+
--INI--
6+
zend_test.zend_mm_observer.enabled=0
7+
opcache.enable=0
8+
--FILE--
9+
<?php
10+
ini_set('zend_test.zend_mm_observer.enabled', 'true');
11+
gc_mem_caches();
12+
ini_set('zend_test.zend_mm_observer.enabled', 'false');
13+
?>
14+
--EXPECTREGEX--
15+
.*garbage collection ended with \d+ bytes collected.*

ext/zend_test/zend_mm_observer.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC
3131
fflush(stdout);
3232
}
3333

34+
static void zend_mm_test_observer_gc(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
35+
{
36+
printf("garbage collection ended with %zu bytes collected\n", len);
37+
fflush(stdout);
38+
}
39+
3440
static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
3541
{
3642
size_t block_len = 0;
@@ -61,7 +67,13 @@ static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled)
6167

6268
if (int_value == 1) {
6369
if (ZT_G(observer) == NULL) {
64-
ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc);
70+
ZT_G(observer) = zend_mm_observer_register(
71+
zend_mm_get_heap(),
72+
zend_mm_test_observer_malloc,
73+
zend_mm_test_observer_free,
74+
zend_mm_test_observer_realloc,
75+
zend_mm_test_observer_gc
76+
);
6577
}
6678
} else {
6779
if (ZT_G(observer) != NULL) {
@@ -88,7 +100,13 @@ void zend_test_mm_observer_minit(INIT_FUNC_ARGS)
88100
void zend_test_mm_observer_rinit(void)
89101
{
90102
if (ZT_G(zend_mm_observer_enabled)) {
91-
ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc);
103+
ZT_G(observer) = zend_mm_observer_register(
104+
zend_mm_get_heap(),
105+
zend_mm_test_observer_malloc,
106+
zend_mm_test_observer_free,
107+
zend_mm_test_observer_realloc,
108+
zend_mm_test_observer_gc
109+
);
92110
printf("ZendMM Observer enabled\n");
93111
fflush(stdout);
94112
}

0 commit comments

Comments
 (0)