Skip to content

Commit 70bdf69

Browse files
observe ZendMM garbage collection
1 parent 10cba17 commit 70bdf69

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
@@ -206,9 +206,21 @@ struct _zend_mm_observer {
206206
void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
207207
void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
208208
void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
209+
void (*gc)(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
209210
zend_mm_observer *next;
210211
};
211212

213+
#define HANDLE_OBSERVERS(heap, use_custom_heap, observer_function, ...) \
214+
if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \
215+
zend_mm_observer *current = heap->observers; \
216+
while (current != NULL) { \
217+
if (current->observer_function != NULL) { \
218+
current->observer_function(__VA_ARGS__ ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
219+
} \
220+
current = current->next; \
221+
} \
222+
}
223+
212224
/*
213225
* Memory is retrieved from OS by chunks of fixed size 2MB.
214226
* Inside chunk it's managed by pages of fixed size 4096B.
@@ -1975,7 +1987,9 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap)
19751987
size_t collected = 0;
19761988

19771989
#if ZEND_MM_CUSTOM
1978-
if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) {
1990+
int use_custom_heap = heap->use_custom_heap;
1991+
if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) {
1992+
HANDLE_OBSERVERS(heap, use_custom_heap, gc ,0);
19791993
return 0;
19801994
}
19811995
#endif
@@ -2074,6 +2088,10 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap)
20742088
}
20752089
} while (chunk != heap->main_chunk);
20762090

2091+
#if ZEND_MM_CUSTOM
2092+
HANDLE_OBSERVERS(heap, use_custom_heap, gc, collected * ZEND_MM_PAGE_SIZE);
2093+
#endif
2094+
20772095
return collected * ZEND_MM_PAGE_SIZE;
20782096
}
20792097

@@ -2503,17 +2521,6 @@ ZEND_API bool is_zend_ptr(const void *ptr)
25032521

25042522
#if ZEND_MM_CUSTOM
25052523

2506-
#define HANDLE_OBSERVERS(observer_function, ...) \
2507-
if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \
2508-
zend_mm_observer *current = heap->observers; \
2509-
while (current != NULL) { \
2510-
if (current->observer_function != NULL) { \
2511-
current->observer_function(__VA_ARGS__ ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2512-
} \
2513-
current = current->next; \
2514-
} \
2515-
}
2516-
25172524
static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
25182525
{
25192526
void *ptr;
@@ -2527,7 +2534,7 @@ static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_D
25272534
// no custom memory manager, only observer present
25282535
ptr = zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25292536
}
2530-
HANDLE_OBSERVERS(malloc, size, ptr)
2537+
HANDLE_OBSERVERS(heap, use_custom_heap, malloc, size, ptr)
25312538
return ptr;
25322539
}
25332540

@@ -2536,7 +2543,7 @@ static ZEND_COLD void ZEND_FASTCALL _efree_custom(void *ptr ZEND_FILE_LINE_DC ZE
25362543
zend_mm_heap *heap = AG(mm_heap);
25372544
int use_custom_heap = heap->use_custom_heap;
25382545

2539-
HANDLE_OBSERVERS(free, ptr)
2546+
HANDLE_OBSERVERS(heap, use_custom_heap, free, ptr)
25402547

25412548
if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) {
25422549
heap->custom_heap.debug._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
@@ -2561,7 +2568,7 @@ static ZEND_COLD void* ZEND_FASTCALL _realloc_custom(void *ptr, size_t size ZEND
25612568
// no custom memory manager, only observer present
25622569
new_ptr = zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25632570
}
2564-
HANDLE_OBSERVERS(realloc, ptr, size, new_ptr)
2571+
HANDLE_OBSERVERS(heap, use_custom_heap, realloc, ptr, size, new_ptr)
25652572
return new_ptr;
25662573
}
25672574
#endif
@@ -3100,7 +3107,8 @@ ZEND_API zend_mm_observer* zend_mm_observer_register(
31003107
zend_mm_heap* heap,
31013108
void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
31023109
void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
3103-
void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
3110+
void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
3111+
void (*gc)(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
31043112
) {
31053113
#if ZEND_MM_CUSTOM
31063114
if (!heap) {
@@ -3112,6 +3120,7 @@ ZEND_API zend_mm_observer* zend_mm_observer_register(
31123120
node->malloc = malloc;
31133121
node->free = free;
31143122
node->realloc = realloc;
3123+
node->gc = gc;
31153124
node->next = NULL;
31163125

31173126
// 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)