lua 常量表優化

yanchengfuke 8年前發布 | 30K 次閱讀 Lua Lua開發

來自: http://blog.codingnow.com/2016/04/lua_table_constants.html

今天花了一天嘗試給 lua vm 做了一點優化:

現在 lua 的函數原型里保留有一張常量表,引用了 string ,number ,nil ,boolean 類型的常量。

table 是不能為常量的,所以當你想迭代一個常量數組的時候,

for _, v in ipairs { "one", "two", "three" } do

其實每次都會臨時構建一張表,并依次插入 "one", "two", "three" 。

或者你想返回一個常量構成的表:

function foo()
  return { x=1, y=2 }
end

每次 foo 函數都會為返回值重新構建 table 。

其實,我們可以認為所有鍵值都是常量的 table ,都有可能是一個常量表。那么,在 parser 階段,和 string 等類型一樣,預先建立好 table 對象,保留在 prototype 的常量表中,可以極大的提高運行性能。

那么在上面這種 return {x=1, y=2} 的寫法中,實際返回的可以僅僅是一個 table proxy ,里面只有一個指向常量表的指針即可。

如果事后我們真的需要改寫這個 table ,再 clone 一份常量表,把這個 table proxy 對象還原成真正的 table 對象即可。也就是所謂的 COW 技術。

由于常量表一定是一個單層簡單表結構,可以直接 memcpy 復制,比一項項添加 key/value 要快很多(實測可以快 3-4 倍)。

我們為之付出的代價僅僅是每次訪問 Table 對象時要多做一次判斷,但收益巨大。

我的實現放在 自己的倉庫 ,有興趣的同學可以看看最近的提交。btw, 暫時只支持 parser ,還沒有支持 dump/undump 。

下面是一個簡單的測試:

function f(a)
end

local t = os.clock()

for i=1, 10000000 do
    f { x=1, y=2 }
end

print(os.clock() -t)

上面這段代碼,在原始 lua 5.3.2 中運行花掉 4.977s ,修改過的版本減少到 1.278s 。

如果在 function f(a) 中修改 a 這個表,加入了 mutable 化過程:

function f(a)
    a.x = 3
end

local t = os.clock()

for i=1, 10000000 do
    f { x=1, y=2 }
end

print(os.clock() -t)

修改后的版本也有巨大的優勢:原始版本 5.234s ,修改版本 1.413s 。

 本文由用戶 yanchengfuke 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!