但是、第二种方法会导致 C 访问数据的成本较大。我们采用 C 代码去处理 vector 数据结构,一定是考虑到性能热点,在语言边界上损失性能感觉不太划算。我觉得或许可以采取一个技巧来加快它。
对于标准的 Lua 实现,构造好的 hash 表,在不添加新 key 的前提下,读写已有的 key ,value 所在的 slot 是不变的。如果我们能记住 slot 的位置,那么就可以绕过 hash 过程、也不需要把 key (这里是一个 string)压栈,直接读写值了。
而且,对于同一个 lua_State
从一个空表开始,按一致的次序写入相同的 key ,内部数据结构也一定相同。我们可以利用这一点,为同类结构一次性生成索引表。
我写了一小段代码验证我的想法,感觉是可行的: 。
你可以先创建一个 4 个 slot 的 hash 表,key 分别是 x y z __vector
。这第 4 个 key __vector
是一个标记,表示这是个规整过的数据结构,x y z 都是浮点数,且一定在固定的 slot 里。
void vector_init(lua_State *L, struct vector_offset *vo)
可以用来生成 slot 号的结构 struct vector_offset
。每个 lua_State
只用生成一次,然后就可以永久保存在 C 的数据结构中。
然后我们用 vector_get
可以获得内部数据结构 Table * ,这个结构定义在 lobject.h 中,是一个内部 h 文件,这里可以借用一下。之后,就可以用宏 X Y Z 去访问这个 Table * 了。
vector_get
中,会检查指定的 table 是否是规整化的 vector 结构,如果不是,就把 x y z 三项读出来,清空 table ,再写回去,并填上 __vector
标记。此处检查 __vector
标记是个很轻量的操作。
这个方案适用于 Lua 5.3 ,我没有在老版本的 Lua 上试过,但想必也是可以用的。它的好处是不需要修改任何 Lua 的实现代码、只需要引入 Lua 本身的内部 h 文件即可。所以利用这组 api 实现的 lua 库是可以和其它库兼容共存的。
来源: http://www.tuicool.com/articles/Mf2EbuA