6969#include "zend.h"
7070#include "zend_API.h"
7171#include "zend_fibers.h"
72+ #include "zend_hrtime.h"
7273
7374#ifndef ZEND_GC_DEBUG
7475# define ZEND_GC_DEBUG 0
@@ -220,6 +221,11 @@ typedef struct _zend_gc_globals {
220221 uint32_t gc_runs ;
221222 uint32_t collected ;
222223
224+ zend_hrtime_t activated_at ;
225+ zend_hrtime_t collector_time ;
226+ zend_hrtime_t dtor_time ;
227+ zend_hrtime_t free_time ;
228+
223229#if GC_BENCH
224230 uint32_t root_buf_length ;
225231 uint32_t root_buf_peak ;
@@ -439,6 +445,10 @@ static void gc_globals_ctor_ex(zend_gc_globals *gc_globals)
439445
440446 gc_globals -> gc_runs = 0 ;
441447 gc_globals -> collected = 0 ;
448+ gc_globals -> collector_time = 0 ;
449+ gc_globals -> dtor_time = 0 ;
450+ gc_globals -> free_time = 0 ;
451+ gc_globals -> activated_at = 0 ;
442452
443453#if GC_BENCH
444454 gc_globals -> root_buf_length = 0 ;
@@ -479,6 +489,10 @@ void gc_reset(void)
479489 GC_G (gc_runs ) = 0 ;
480490 GC_G (collected ) = 0 ;
481491
492+ GC_G (collector_time ) = 0 ;
493+ GC_G (dtor_time ) = 0 ;
494+ GC_G (free_time ) = 0 ;
495+
482496#if GC_BENCH
483497 GC_G (root_buf_length ) = 0 ;
484498 GC_G (root_buf_peak ) = 0 ;
@@ -488,6 +502,8 @@ void gc_reset(void)
488502 GC_G (zval_marked_grey ) = 0 ;
489503#endif
490504 }
505+
506+ GC_G (activated_at ) = zend_hrtime ();
491507}
492508
493509ZEND_API bool gc_enable (bool enable )
@@ -1469,6 +1485,8 @@ ZEND_API int zend_gc_collect_cycles(void)
14691485 bool should_rerun_gc = 0 ;
14701486 bool did_rerun_gc = 0 ;
14711487
1488+ zend_hrtime_t start_time = zend_hrtime ();
1489+
14721490rerun_gc :
14731491 if (GC_G (num_roots )) {
14741492 int count ;
@@ -1482,6 +1500,7 @@ ZEND_API int zend_gc_collect_cycles(void)
14821500 stack .next = NULL ;
14831501
14841502 if (GC_G (gc_active )) {
1503+ GC_G (collector_time ) += zend_hrtime () - start_time ;
14851504 return 0 ;
14861505 }
14871506
@@ -1561,6 +1580,7 @@ ZEND_API int zend_gc_collect_cycles(void)
15611580 *
15621581 * The root buffer might be reallocated during destructors calls,
15631582 * make sure to reload pointers as necessary. */
1583+ zend_hrtime_t dtor_start_time = zend_hrtime ();
15641584 idx = GC_FIRST_ROOT ;
15651585 while (idx != end ) {
15661586 current = GC_IDX2PTR (idx );
@@ -1582,11 +1602,13 @@ ZEND_API int zend_gc_collect_cycles(void)
15821602 }
15831603 idx ++ ;
15841604 }
1605+ GC_G (dtor_time ) += zend_hrtime () - dtor_start_time ;
15851606
15861607 if (GC_G (gc_protected )) {
15871608 /* something went wrong */
15881609 zend_get_gc_buffer_release ();
15891610 zend_fiber_switch_unblock ();
1611+ GC_G (collector_time ) += zend_hrtime () - start_time ;
15901612 return 0 ;
15911613 }
15921614 }
@@ -1595,6 +1617,7 @@ ZEND_API int zend_gc_collect_cycles(void)
15951617
15961618 /* Destroy zvals. The root buffer may be reallocated. */
15971619 GC_TRACE ("Destroying zvals" );
1620+ zend_hrtime_t free_start_time = zend_hrtime ();
15981621 idx = GC_FIRST_ROOT ;
15991622 while (idx != end ) {
16001623 current = GC_IDX2PTR (idx );
@@ -1645,6 +1668,8 @@ ZEND_API int zend_gc_collect_cycles(void)
16451668 current ++ ;
16461669 }
16471670
1671+ GC_G (free_time ) += zend_hrtime () - free_start_time ;
1672+
16481673 zend_fiber_switch_unblock ();
16491674
16501675 GC_TRACE ("Collection finished" );
@@ -1666,6 +1691,7 @@ ZEND_API int zend_gc_collect_cycles(void)
16661691finish :
16671692 zend_get_gc_buffer_release ();
16681693 zend_gc_root_tmpvars ();
1694+ GC_G (collector_time ) += zend_hrtime () - start_time ;
16691695 return total_count ;
16701696}
16711697
@@ -1679,6 +1705,10 @@ ZEND_API void zend_gc_get_status(zend_gc_status *status)
16791705 status -> threshold = GC_G (gc_threshold );
16801706 status -> buf_size = GC_G (buf_size );
16811707 status -> num_roots = GC_G (num_roots );
1708+ status -> application_time = zend_hrtime () - GC_G (activated_at );
1709+ status -> collector_time = GC_G (collector_time );
1710+ status -> dtor_time = GC_G (dtor_time );
1711+ status -> free_time = GC_G (free_time );
16821712}
16831713
16841714ZEND_API zend_get_gc_buffer * zend_get_gc_buffer_create (void ) {
0 commit comments