Lua 5.1#运算符和字符串比较(性能)

时间:2014-11-12 12:32:44

标签: performance lua comparison

为此:

b = #{1,2,3}
c = 'deadbeef' == 'deadbabe'

b是在O(n)还是O(1)中计算的?在什么情况下?行为是否一致,或者像稀疏数组行为一样依赖于上下文? 是字符串比较O(1)还是O(n)?我知道字符串是不可变的,Lua比较哈希值但是如果2个不同的字符串哈希到相同的值呢? 请不要回答"不要担心低级行为,儿子"。我对低级行为感兴趣。谢谢。

修改

3)#的结果是存储在某个地方,还是每次我为同一个数组调用它时都会计算出来?

2 个答案:

答案 0 :(得分:7)

表的长度在O(log n)中计算。该算法大致如下:

  • 尝试通过一步来找到映射到nil的某个整数索引。步长每次加倍。 (如果在数组部分的末尾找到nil值,则可以跳过此部分。)
  • 当找到这样的索引时,在该索引与最后一个已知的非nil索引之间的间隔上使用分而治之算法来查找非nil值,后面跟一个{ {1}}值。

查看详情here。如果您有一个连续的值序列,此算法可以正常工作,但如果数组之间有空洞,则会产生意外结果。

编辑:内置nil运算符的结果未缓存,因此每次在表上使用#时都会运行上述算法(不使用#元方法)。

关于字符串比较(用于相等): 较新的Lua版本在内部有两种类型的字符串:短字符串(通常最多40个字节)和长字符串。使用__len比较长字符串(如果长度匹配),则得到memcmp。另一方面,短字符串是“interned”,这意味着当您在Lua中创建某个短字符串时,将检查是否已存在具有相同内容的字符串。如果是这样,则重用旧的字符串对象,并且不分配新的字符串。这意味着您可以简单地比较内存地址以检查短字符串的相等性,即O(n)

答案 1 :(得分:4)

Lua字符串存储在表中以避免创建相同字符串的重复项,因此每次创建字符串时,都需要对其进行哈希处理,并将其与具有相同哈希值的任何内容进行比较。

创建后字符串对象的比较是O(1),因为Lua已经确保它们引用了一个唯一的字符串,因此Lua只是比较了底层指针。

  

因为所有字符串都被内化,字符串相等就变成了    指针相等

     

#define eqstr(a,b) ((a) == (b)) lstring.h

x = "deadbeef" -- put in string table
y = "deadbabe" -- put in string table
c = x == y    -- compared pointers

对于您提供的表格案例:

ltabl.c:int luaH_getn (Table *t)的实施:

t = {1, 2, 3} -- requires creating a table, hashing all the values etc.
b = #t    -- constant time as array part is full and no hash part (ergo # is the array size)
t = [3] = nil
b = #t   -- boundary inside array part, binary search in array,  b=2
b = #t   -- another binary search
t = {1, 2, 3, [1000]=4} 
b = #t   -- array is full, and 4 is not a key in the hash, b = 3