本篇文章,主要探讨一下lua中的字符串缓存管理(涉及到的文件 lstring.c )。
在lua的9种数据类型中,字符串是属于可以被GC回收的类型。在lua中,操作字符串实际上是在操作字符串引用,当字符串不在被使用的时候,GC会通过一定算法回收。
--lua9种数据类型:
字符串分配
--源码:
ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
--该行代码申请放置字符串的内存,luaM_malloc是申请内存的一个宏定义,调用上篇文章中提到的luaM_realloc_ 函数来来分配内存,在lua中字符串是用结构
表示的,所以申请的内存大小是(l+1)*sizeof(char)+sizeof(TString),内存分布:TString+str+'/0',然后给TString赋值hash code, len,marted,reserved,拷贝字符串。
tb = &G(L)->strt;
h = lmod(h, tb->size);
ts->tsv.next = tb->hash[h]; /* chain new entry */
tb->hash[h] = obj2gco(ts);
tb->nuse++;
--接下来,将分配的字符串挂到全局字符串管理对象strt上
if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
--对字符串大小的扩充
字符串缓存
--源码:
unsigned int h = cast(unsigned int, l); /* seed */
size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
for (l1=l; l1>=step; l1-=step) /* compute hash */
h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
---根据字符串长度l和字符串内容str计算字符串hash code,字符串hash code用作该字符串的key,后续用作字符串缓存key,这个算法可以保证key-value一一对应。
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
o != NULL;
o = o->gch.next) {
TString *ts = rawgco2ts(o);
if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
/* string may be dead */
if (isdead(G(L), o)) changewhite(o);
return ts;
}
}
--在字符串全局管理对象中查找该字符串,如果查到就使用该字符串返回,否则:
return newlstr(L, str, l, h);
申请内存放置字符串。