Skip to content

Commit 2afc837

Browse files
committed
Allow access to some garbage collection internals (Benjamin Eberlei)
1 parent 609385b commit 2afc837

File tree

4 files changed

+64
-0
lines changed

4 files changed

+64
-0
lines changed

Zend/tests/gc_037.phpt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
GC 037: gc_status()
3+
--INI--
4+
zend.enable_gc = 1
5+
--FILE--
6+
<?php
7+
var_dump(gc_status());
8+
$a = array();
9+
$a[] =& $a;
10+
unset($a);
11+
gc_collect_cycles();
12+
gc_collect_cycles();
13+
var_dump(gc_status());
14+
--EXPECT--
15+
array(3) {
16+
["gc_runs"]=>
17+
int(0)
18+
["collected"]=>
19+
int(0)
20+
["gc_threshold"]=>
21+
int(10001)
22+
}
23+
array(3) {
24+
["gc_runs"]=>
25+
int(1)
26+
["collected"]=>
27+
int(1)
28+
["gc_threshold"]=>
29+
int(10001)
30+
}

Zend/zend_builtin_functions.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "zend.h"
2323
#include "zend_API.h"
24+
#include "zend_gc.h"
2425
#include "zend_builtin_functions.h"
2526
#include "zend_constants.h"
2627
#include "zend_ini.h"
@@ -85,6 +86,7 @@ static ZEND_FUNCTION(gc_collect_cycles);
8586
static ZEND_FUNCTION(gc_enabled);
8687
static ZEND_FUNCTION(gc_enable);
8788
static ZEND_FUNCTION(gc_disable);
89+
static ZEND_FUNCTION(gc_status);
8890

8991
/* {{{ arginfo */
9092
ZEND_BEGIN_ARG_INFO(arginfo_zend__void, 0)
@@ -293,6 +295,7 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
293295
ZEND_FE(gc_enabled, arginfo_zend__void)
294296
ZEND_FE(gc_enable, arginfo_zend__void)
295297
ZEND_FE(gc_disable, arginfo_zend__void)
298+
ZEND_FE(gc_status, arginfo_zend__void)
296299
ZEND_FE_END
297300
};
298301
/* }}} */
@@ -385,6 +388,21 @@ ZEND_FUNCTION(gc_disable)
385388
}
386389
/* }}} */
387390

391+
/* {{{ proto array gc_status(void)
392+
Returns current GC statistics */
393+
ZEND_FUNCTION(gc_status)
394+
{
395+
zend_gc_status status;
396+
397+
zend_gc_get_status(&status);
398+
399+
array_init_size(return_value, 3);
400+
401+
add_assoc_long_ex(return_value, "gc_runs", sizeof("gc_runs")-1, (long)status.gc_runs);
402+
add_assoc_long_ex(return_value, "collected", sizeof("collected")-1, (long)status.collected);
403+
add_assoc_long_ex(return_value, "gc_threshold", sizeof("gc_threshold")-1, (long)status.gc_threshold);
404+
}
405+
388406
/* {{{ proto int func_num_args(void)
389407
Get the number of arguments that were passed to the function */
390408
ZEND_FUNCTION(func_num_args)

Zend/zend_gc.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,13 @@ ZEND_API int zend_gc_collect_cycles(void)
14421442
return count;
14431443
}
14441444

1445+
ZEND_API void zend_gc_get_status(zend_gc_status *status)
1446+
{
1447+
status->gc_runs = GC_G(gc_runs);
1448+
status->collected = GC_G(collected);
1449+
status->gc_threshold = GC_G(gc_threshold);
1450+
}
1451+
14451452
/*
14461453
* Local variables:
14471454
* tab-width: 4

Zend/zend_gc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
#define ZEND_GC_H
2424

2525
BEGIN_EXTERN_C()
26+
27+
typedef struct _zend_gc_status {
28+
uint32_t gc_runs;
29+
uint32_t collected;
30+
uint32_t gc_threshold;
31+
} zend_gc_status;
32+
2633
ZEND_API extern int (*gc_collect_cycles)(void);
2734

2835
ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref);
@@ -39,6 +46,8 @@ ZEND_API zend_bool gc_protected(void);
3946
/* The default implementation of the gc_collect_cycles callback. */
4047
ZEND_API int zend_gc_collect_cycles(void);
4148

49+
ZEND_API void zend_gc_get_status(zend_gc_status *status);
50+
4251
void gc_globals_ctor(void);
4352
void gc_globals_dtor(void);
4453
void gc_reset(void);

0 commit comments

Comments
 (0)