Lua堆栈操作的复杂性(Lua C API)

Complexity of Lua stack operations (Lua C API)

在Lua C API中,它提供了Lua文档中提到的夫妇堆栈操作功能

1
2
3
4
5
6
int   lua_gettop (lua_State *L);
void  lua_settop (lua_State *L, int index);
void  lua_pushvalue (lua_State *L, int index);
void  lua_remove (lua_State *L, int index);
void  lua_insert (lua_State *L, int index);
void  lua_replace (lua_State *L, int index);

我的第一个问题是,这些功能的复杂性是什么? 是O(1)还是O(| index |)? 我检查了Lua手册,似乎Lua有两种不同的堆栈实现(基于堆栈和基于寄存器)。

更具体地说,如果我想阅读并弹出lua堆栈中的前三个元素,可以想到以下两个实现,我可以知道哪个是性能更高/建议的方式吗?

解决方案1-读取并弹出每个值:

1
2
3
4
5
for (int i = 0; i < 3; ++i) {
  values[i] = lua_tostring(lua_state, -1);
  ...
  lua_pop(lua_state, 1);
}

解决方案2-阅读全部然后弹出全部:

1
2
3
4
5
for (int i = 0; i < 3; ++i) {
  values[i] = lua_tostring(lua_state, -1 - i);
}
...
lua_pop(lua_state, 3);


Lua 5.3将lua_pop定义为

1
#define lua_pop(L,n)            lua_settop(L, -(n)-1)

lua_settop可以在这里看到; 它将用nil填充堆栈插槽,以便可以gc'd值。 因此它是带有arg 1的O(1)。

您可以读取O(1)中的每个值,并且N个值的弹出值为O(N)。

因此,您的两种方法应该大致相同。

关于:读取O(1)中的值,函数index2addr是将堆栈偏移量转换为地址的函数。