2015-12-26 24 views
2

我正在向ws2812模塊添加一些代碼,以便能夠在某些類型的可重用緩衝區中存儲led值。NodeMCU/Lua性能問題

當前版本爲there

我有兩個問題。

首先我想要一些「OO風格」的界面。所以我做:

local buffer = ws2812.newBuffer(300); 
for j = 0,299 do 
    buffer:set(j, 255, 255, 255) 
end 
buffer:write(pin); 

這裏的probleme是buffer:set在每個循環轉,這是昂貴的解決(這個循環需要〜20.2ms):

8  [2]  FORPREP   1 6  ; to 15 
9  [3]  SELF   5 0 -7 ; "set" 
10  [3]  MOVE   7 4 
11  [3]  LOADK   8 -8 ; 255 
12  [3]  LOADK   9 -8 ; 255 
13  [3]  LOADK   10 -8 ; 255 
14  [3]  CALL   5 6 1 
15  [2]  FORLOOP   1 -7 ; to 9 

我找到了一個解決方法這個問題這看起來並不「好看」:

local buffer = ws2812.newBuffer(300); 
local set = getmetatable(buffer).set; 
for j = 0,299 do 
    set(buffer, j, 255, 255, 255) 
end 
buffer:write(pin); 

它運作良好(4.3ms的循環,超過4倍的速度),但它更像是一個黑客。 :/有沒有更好的方法來「緩存」緩衝區:設置分辨率?

第二個問題,在我的C代碼,我用:

ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer"); 

哪還給我的緩衝PTR,並檢查它是否是一個真正的ws2812.buffer。但是這個電話很糟糕:在我的ESP8266上,〜50us。如果每次通話都完成(例如,我的300次buffer:set),那就是〜15ms!

有沒有更好的方法來獲取一些用戶數據並檢查它的類型,還是應該在我的結構開始處添加一些「金絲雀」來做我自己的檢查(與50us相比,它幾乎是「免費的」)。 ..)?

+0

請報告第二個版本比第一個版本快多少。 – lhf

+0

添加後,4.3ms而不是20.2ms! – Alkorin

+0

最好的方法是矢量化API函數,例如'setvec(jstart,jend,rstart,rend,bstart,gend,bstart,bend)',那麼你有**一個** C庫調用:'buffer:set(0,299,255,255,255, 255,255,255)',並且一個表查找的開銷在很大程度上是不相關的。 – TerryE

回答

3

,使它看起來更小的黑客,你可以嘗試使用

local set = buffer.set 

這本質上是相同的代碼,但沒有getmetatable爲元表通過__index元方法隱含使用。

在我們的項目上,我們自己實現了luaL_checkudata。 一個選項 - 正如你同樣的建議 - 是使用一個包裝類型的包裝對象。由於所有用戶數據都被假定爲封裝在包裝器中,我們可以使用它來獲取並確認用戶數據的類型。但是沒有完成基準測試,而是使用了測試metatables。

我會說測試metatables比包裝要慢,因爲luaL_checkudata做了很多工作來獲取和測試metatables,並且通過包裝我們可以直接訪問該類型。然而,基準測試可以肯定。

+0

事實上,它的工作原理...不知道爲什麼我堅持使用冒號語法:/謝謝! – Alkorin

+0

@Alkorin我做了一些非常**差的測試,它清楚地顯示了使用包裝代替metatable檢查時的加速。這裏是我混淆的代碼:https://gist.github.com/Rochet2/c61cc0ecb05ecbea2291 – Rochet2