我真的需要在Lua中有一个整数类型。
我的意思是定义通常运算符(/ * +等)并且表现得像整数的类型,内部表示并不重要。
用表格实现这样的事情非常简单,但问题在于,我尝试过了,性能非常糟糕(当然)。这是我的部分实现:
function num_op(a, b, calc_func)
local atype = pytype(a)
local btype = pytype(b)
local a_val, b_val
a_val = (atype == "Integer" or atype == "Double") and a[1] or a
b_val = (btype == "Integer" or btype == "Double") and b[1] or b
val = calc_func(a_val, b_val)
if atype == "Integer" and btype == "Integer" then
return Integer:create(val)
else
return Double:create(val)
end
end
numeric_mt = {
__add = function(a, b)
return num_op(a, b, function(a,b) return a + b end)
end,
__sub = function(a, b)
return num_op(a, b, function(a,b) return a - b end)
end,
__div = function(a, b)
return num_op(a, b, function(a,b) return a / b end)
end,
__mul = function(a, b)
return num_op(a, b, function(a,b) return a * b end)
end,
__tostring = function(a)
return tostring(a[1])
end
}
-----------------------------
-- Integer type definition --
-----------------------------
Integer = {}
Integer_mt = table.copy(numeric_mt)
Integer_mt["__index"] = Integer
function Integer:create(value)
local new_inst = {math.floor(value)}
setmetatable(new_inst, Integer_mt)
return new_inst
end
function Integer:className()
return "Integer"
end
据我了解,主要的性能损失来自于非常频繁的分配内存。LuaJit 能够很好地优化操作函数,但对元表的分配无能为力。有没有人认为通过自定义 C 实现和用户数据可以做得更好?或者说我的追求是不可能实现的?
注:我知道 Lua 没有整数。我也知道可以使用 math 库获得相同的结果。我想要的是在使用整数时具有完全的透明度,除了创建阶段以外。
编辑:我会在这里添加额外的信息,使所有内容仍然集中在一起。
@Mud:我需要在一定程度上拥有“透明”的混合算术运算,就像 Python/Ruby 等语言中一样,同时尽可能提高性能。我正在将 LuaJIT 作为编译器的目标,对于不支持 LuaJIT 的平台,我将使用普通的 Lua。这对于性能特征非常重要。
这意味着我希望能够这样做:
a = int(5) -- Integer value
b = int(2) -- Another Integer
c = 2 -- Double
d = a / b -- == 2 , integer arithmetics
e = a / c -- == 2.5, floating point arithmetics
我可以通过上面展示的实现方法来达到一定程度的目标。问题在于,每个数字都需要装箱,因此我正在减慢操作速度。我可以使用调试库来重载数字的元表,但是:
- 我不知道这个功能在生产质量软件中可靠性如何。
- 由于要使用(number):get()才能统一数字接口,因此它仍会降低数字的性能。
昨晚我自己在C中实现了整数。虽然它比我在常规lua中的天真实现和内联调用math.floor的方式有所改善,但在使用LuaJIT时却不太清晰,因为内联调用仍然比C实现快得多。
另一种解决方法是始终使用非装箱数字,并在编译器中使用某种类型传播来跟踪整数,并在需要时使用适当的内联操作。但是,这种解决方案的复杂性更大,而且有点违背使用Lua / LuaJIT作为后端的初衷。
我将尝试您的实现方法,但我怀疑它不会比LuaJIT中的内联调用更好。很可能我追求的目标(既具有double和整数的透明操作,又接近于luaJIT上的内联调用性能)根本不可能实现。非常感谢您的帮助。
@miky:谢谢,看起来很好,但我怀疑我无法将其打补丁到luaJIT中,如果我不能,它对我的目标就失去了所有兴趣。