【发布时间】:2016-04-01 00:42:58
【问题描述】:
我正在向 ws2812 模块添加一些代码,以便能够拥有某种可重用的缓冲区,我们可以在其中存储 LED 值。
当前版本是there。
我有两个问题。
首先我想要一些“OO 风格”的界面。所以我做了:
local buffer = ws2812.newBuffer(300);
for j = 0,299 do
buffer:set(j, 255, 255, 255)
end
buffer:write(pin);
这里的问题是buffer:set 在每个循环转弯处被解析,这是昂贵的(这个循环需要大约 20.2 毫秒):
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.3 毫秒,快 4 倍以上),但它更像是一个 hack。 :/ 有没有更好的方法来“缓存”缓冲区:设置分辨率?
第二个问题,在我的 C 代码中,我使用:
ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer");
它会返回我的缓冲区 ptr 并检查它是否真的是 ws2812.buffer。但是这个电话很慢:在我的 ESP8266 上,~50us。如果每次通话都完成(例如,我的 300 次 buffer:set),大约需要 15 毫秒!
有没有更好的方法来获取一些用户数据并检查其类型,或者我应该在结构的开头添加一些“金丝雀”来进行自己的检查(与 50us 相比,这几乎是“免费的”...... .)?
【问题讨论】:
-
请报告第二个版本比第一个版本快多少。
-
在帖子中添加,4.3 毫秒而不是 20.2 毫秒!
-
最好的方法是矢量化 API 函数,例如
setvec(jstart, jend, rstart, rend, bstart, gend, bstart, bend),那么你有 一个 C 库调用:buffer:set(0, 299, 255, 255, 255, 255, 255, 255)并且单表查找的开销在很大程度上是无关紧要的。 -
是也不是@TerryE,我无法预测下一个颜色:它主要来自查找表和/或一些数学函数。这就是我搜索优化简单调用的原因;)但在某些情况下,我计划处理表以便能够重用一些存储的模式:
set(start, {{g, r, b},{g, r, b},...})