Lua 表中的字段访问比 cdata 字段访问更快吗?

假设我有一个 cdata 变量(一个 FFI 查询的结果)。然后我将它的字段复制到一个 Lua 表中。那么访问 Lua 表的字段和原始的 cdata 变量的字段哪个更快呢?

点赞
用户1843616
用户1843616

让我们来检查一下

使用 jit:

./tarantool -l clock -l ffi
Tarantool 2.3.1-18-ga5a2bb28a
type 'help' for interactive help
tarantool> ffi.cdef[[ typedef struct test { int field; } ]]
---
...

tarantool> T = ffi.typeof('struct test')
---
...

tarantool> F = T({12345})
---
...

tarantool> L = {field = 12345}
---
...
tarantool> local st = clock.proc() for i=1,1e8 do local x = F.field end return clock.proc() - st
---
- 0.036895
...

tarantool> local st = clock.proc() for i=1,1e8 do local x = L.field end return clock.proc() - st
---
- 0.037841
...

而没有 jit:

tarantool> jit.off()
---
...
tarantool> local st = clock.proc() for i=1,1e6 do local x = F.field end return clock.proc() - st
---
- 0.198209
...
tarantool> local st = clock.proc() for i=1,1e6 do local x = L.field end return clock.proc() - st
---
- 0.010116
...

因此,总结如下:

  • 使用 jit 时它们几乎相当
  • 没有 jit 时,表比 ffi 快 20 倍,但……比使用 jit 慢 25 倍
2020-05-19 11:38:40
用户4609359
用户4609359

禁用JIT时,由于LuaJIT表的内部结构和碰撞处理优化(例如Brent的变化),表键查找方式更快。对于“cdata”,TGETS/TGETV意味着元方法查找及其之后的执行。此处是实施字段(即键)查找的方法。

启用JIT后,表格槽和结构字段地址/偏移量都会与traces专门化,并在其之前执行几个断言守卫。忽略此类断言失败(例如由于表格重新分配导致槽地址无效的情况),性能差异可视为可以忽略不计。

我也看到了由@mons-anderson进行的良好基准测试,证实了这一点。

2020-05-19 12:04:20