Learn And Life.

Php垃圾回收

zend_gc_globals结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
typedef struct _zend_gc_globals {
zend_bool gc_enabled;
zend_bool gc_active;
zend_bool gc_full;
gc_root_buffer *buf; /* preallocated arrays of buffers */
gc_root_buffer roots; /* list of possible roots of cycles */
gc_root_buffer *unused; /* list of unused buffers */
gc_root_buffer *first_unused; /* pointer to first unused buffer */
gc_root_buffer *last_unused; /* pointer to last unused buffer */
gc_root_buffer to_free; /* list to free */
gc_root_buffer *next_to_free;
uint32_t gc_runs;
uint32_t collected;
#if GC_BENCH
uint32_t root_buf_length;
uint32_t root_buf_peak;
uint32_t zval_possible_root;
uint32_t zval_buffered;
uint32_t zval_remove_from_buffer;
uint32_t zval_marked_grey;
#endif
gc_additional_buffer *additional_buffer;
} zend_gc_globals;

说明:
gc_enabled 是否开启了GC
gc_active 是否GC正在运行
gc_full GC缓冲区是否已经满le
buf 预分配总的缓冲区大小
roots 可能需要回收对象列表
unused 未使用的缓存区
first_unused 未使用的缓冲区的第一个元素
last_unused 未使用的缓冲区的最后一个元素
to_free 垃圾列表
next_to_free 指一个垃圾列表元素
gc_runs GC运行次数
collected 是否垃圾收集完成
additional_buffer 其它缓冲区

GC初始化gc_globals

gc_globals_ctor -> ts_allocate_id -> gc_globals_ctor_ex

```

ZEND_API void gc_globals_ctor(void)
{

#ifdef ZTS
ts_allocate_id(&gc_globals_id, sizeof(zend_gc_globals), (ts_allocate_ctor) gc_globals_ctor_ex, (ts_allocate_dtor) root_buffer_dtor);

#else
gc_globals_ctor_ex(&gc_globals);

#endif
}

参数说明:
rsrc_id 全局资源id (int型)
size 资源大小
ctor 构造器
dtor 析构器

TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
{
int i;
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, “Obtaining a new resource id, %d bytes”, size));
/
加互斥锁 /
tsrm_mutex_lock(tsmm_mutex);
/
生成全局资源id / rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, “Obtained resource id %d”, rsrc_id));
/
注册新的资源到全局资源表 /
if (resource_types_table_size < id_count) { /
如果资源表的大小太小,则调整资源表的大小 /
/
扩展资源表的内存空间 /
resource_types_table = (tsrm_resource_type
) realloc(resource_types_table, sizeof(tsrm_resource_type)id_count);
/
如果内存分配失败,解锁并返回 /
if (!resource_types_table) {
tsrm_mutex_unlock(tsmm_mutex);
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, “Unable to allocate storage for resource”));
rsrc_id = 0;
return 0;
}
/ 如果分配成功,则修改资源表的大小 /
resource_types_table_size = id_count;
}
/ 注册全局资源对象 /
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(rsrc_id)].size = size;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(
rsrc_id)].ctor = ctor;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(rsrc_id)].dtor = dtor;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(
rsrc_id)].done = 0;
/ 遍历线程表,同步全局资源到各个线程对象 /
for (i=0; icount < id_count) {
int j;
/ 扩展线程资源数据内存空间 /
p->storage = (void ) realloc(p->storage, sizeof(void )id_count);
/
新增资源分配内存空间 /
for (j=p->count; jstorage[j] = (void
) malloc(resource_types_table[j].size);
if (resource_types_table[j].ctor) {
/ 调用构造器,初始化gc_globals对象 /
resource_types_table[j].ctor(p->storage[j]);
}
}
/ 修改线程资源数量 /
p->count = id_count;
}
/ 同步下一个线程对象 /
p = p->next;
}
}
/ 资源初始化完毕,解锁 /
tsrm_mutex_unlock(tsmm_mutex);
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, “Successfully allocated new resource id %d”, rsrc_id));
/
全局资源id /
return
rsrc_id;
}

/ 初始化gc_globals对象 /
static void gc_globals_ctor_ex(zend_gc_globals *gc_globals)
{
gc_globals->gc_enabled = 0;
gc_globals->gc_active = 0;

gc_globals->buf = NULL;

gc_globals->roots.next = &gc_globals->roots;
gc_globals->roots.prev = &gc_globals->roots;
gc_globals->unused = NULL;
gc_globals->next_to_free = NULL;

gc_globals->to_free.next = &gc_globals->to_free;
gc_globals->to_free.prev = &gc_globals->to_free;

gc_globals->gc_runs = 0;
gc_globals->collected = 0;

gc_globals->additional_buffer = NULL;

#if GC_BENCH
gc_globals->root_buf_length = 0;
gc_globals->root_buf_peak = 0;
gc_globals->zval_possible_root = 0;
gc_globals->zval_buffered = 0;
gc_globals->zval_remove_from_buffer = 0;
gc_globals->zval_marked_grey = 0;

#endif
}