参考资料:
引用计数
源码: include/phenom/refcnt.h
typedef int ph_refcnt_t;
void ph_refcnt_add(ph_refcnt_t *ref)
// Returns true if we just released the final reference
bool ph_refcnt_del(ph_refcnt_t *ref)
引用计数管理对象的生命期
void ph_string_delref(ph_string_t *str)
{
if (!ph_refcnt_del(&str->ref)) {
return;
}
if (str->mt >= 0) {
ph_mem_free(str->mt, str->buf);
str->mt = PH_MEMTYPE_INVALID;
}
if (str->slice) {
ph_string_delref(str->slice);
str->slice = 0;
}
str->buf = 0;
if (!str->onstack) {
ph_mem_free(mt_string, str);
}
}
Counter
源码: corelib/counter.c; include/phenom/counter.h; tests/counter.c; corelib/debug_console.c
计数器。 用来了解事物发生的频率。实际用在memory, job子系统中。
scope就是一系列在逻辑上处于同一组的counter的集合概念。
在使用counter的时候最初就需要创建scope。
在定义scope的时候需要确定该scope内最多能有多少个counter注册进去,这个叫slot。
scope互相之间可以有父子继承关系。
我们要创建block的scenario只有两个:
当你在同一个线程内需要频繁进行计数器更新的时候;
当你在一个线程内对多个计数器进行更新,并期望这个操作尽可能快的时候;
开启debug-console, 可以输出系统的计数。
~$> echo counters | nc -UC /tmp/phenom-debug-console
iosched/dispatched 5144
iosched/timer_busy 0
iosched/timer_ticks 5035
memory.ares.channel/allocs 1
memory.ares.channel/bytes 104
memory.ares.channel/frees 0
memory.ares.channel/oom 0
上面的最高层的scope是memory和iosched。 memory的子scope是area, area的子scope是channel.
channel里面有4个slots, 分别记录了4个counter. name分别是alloc, bytes, frees, oom.
对应的counter分别是1, 104, 0, 0.
memory
源码:corelib/memory.c; include/phenom/memory; tests/memory.c; corelib/debug_console.c
基于counter子系统的内存分配器。
通过下面2个函数注册新的memtype。
ph_memtype_t ph_memtype_register(const ph_memtype_def_t *def);
ph_memtype_t ph_memtype_register_block(
uint8_t num_types,
const ph_memtype_def_t *defs,
ph_memtype_t *types);
memtype支持的操作,malloc, realloc, free
void *ph_mem_alloc(ph_memtype_t memtype)
void *ph_mem_alloc_size(ph_memtype_t memtype, uint64_t size)
void *ph_mem_realloc(ph_memtype_t memtype, void *ptr, uint64_t size)
void ph_mem_free(ph_memtype_t memtype, void *ptr)
通过下面函数就可以了解内存的分配情况
void ph_mem_stat(ph_memtype_t memtype, ph_mem_stats_t *stats);
struct ph_mem_stats {
/* the definition */
const ph_memtype_def_t *def;
/* current amount of allocated memory in bytes */
uint64_t bytes;
/* total number of out-of-memory events (allocation failures) */
uint64_t oom;
/* total number of successful allocation events */
uint64_t allocs;
/* total number of calls to free */
uint64_t frees;
/* total number of calls to realloc (that are not themselves
* equivalent to an alloc or free) */
uint64_t reallocs;
};
开启debug-console, 可以输出内存使用情况 (非常酷)
$> echo memory | nc -UC /tmp/phenom-debug-console
WHAT BYTES OOM ALLOCS FREES REALLOC
threadpool/pool 832 0 1 0 0
threadpool/ringbuf 8480 0 2 0 0
hashtable/table 3136 0 3 0 0
hook/hook 8 0 1 0 0
hook/head 0 0 0 0 0
hook/string 19 0 1 0 0
hook/unreg 0 0 0 0 0
stream/stream 272 0 2 0 0
buffer/object 120 0 3 0 0
buffer/8k 16384 0 2 0 0
buffer/16k 0 0 0 0 0
buffer/32k 0 0 0 0 0
buffer/64k 0 0 0 0 0
buffer/vsize 0 0 0 0 0
buffer/queue 48 0 2 0 0
buffer/queue_ent 64 0 2 0 0
strings
源码: corelib/string.c; include/phenom/string.c; tests/string.c;
设计目标: http://facebook.github.io/libphenom/#string
实现
typedef struct ph_string ph_string_t;
struct ph_string {
ph_refcnt_t ref; // 引用计数
ph_memtype_t mt;
uint32_t len, alloc; // 使用字节数,总字节数
char *buf; // 指向实际的存储
ph_string_t *slice;
bool onstack; // 是否在stack上
};
其中参数mt的值, 用负的表示stack-based growable,正的表示heap-allocated growable
ph_result_t ph_string_append_buf(ph_string_t *str,
const char *buf, uint32_t len)
{
if (len + str->len > str->alloc) {
// Not enough room
if (str->mt == PH_STRING_STATIC) {
// Just clamp to the available space
len = str->alloc - str->len;
} else {
// Grow it
uint32_t nsize = ph_power_2(str->len + len);
char *nbuf;
// Negative memtypes encode the desired memtype as the negative
// value. Allocate a buffer from scratch using the desired memtype
if (str->mt < 0) {
nbuf = ph_mem_alloc_size(-str->mt, nsize);
} else {
nbuf = ph_mem_realloc(str->mt, str->buf, nsize);
}
if (nbuf == NULL) {
return PH_NOMEM;
}
if (str->mt < 0) {
// Promote from static growable to heap allocated growable
memcpy(nbuf, str->buf, str->len);