2015-12-26 8 views
2

Я добавляю код в модуль ws2812, чтобы иметь возможность использовать буфер многократного использования, где мы могли бы хранить значения ведомого.Проблемы с производительностью NodeMCU/Lua

Текущая версия: there.

У меня две проблемы.

Сначала я хотел иметь интерфейс «OO-style». Так что я сделал:

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. Но этот вызов sloooooow: на моем ESP8266, ~ 50us. Если это делается при каждом вызове (например, для моего 300 раз buffer:set), это ~ 15 мс!

Есть ли лучший способ получить некоторые данные пользователя и проверить его тип, или я должен добавить некоторую «канарейку» в начале моей структуры, чтобы выполнить мою собственную проверку (которая почти будет «бесплатной» по сравнению с 50us. ..)?

+0

Просьба сообщить, насколько быстрее вторая версия сравнивается с первой. – lhf

+0

Добавлено в сообщение, 4,3 мс вместо 20,2 мс! – 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 происходит медленнее, чем упаковка, так как luaL_checkudata выполняет большую работу по получению и тестированию метаданных, и с упаковкой у нас есть доступ к типу напрямую. Однако бенчмаркинг будет точно.

+0

Действительно, это работает ... dunno, почему я застрял в синтаксисе двоеточия:/Спасибо! – Alkorin

+0

@Alkorin Я сделал некоторые ** очень ** плохое тестирование, и он явно показывает скорость при использовании обертки вместо метатетируемой проверки. Вот код, с которым я столкнулся: https://gist.github.com/Rochet2/c61cc0ecb05ecbea2291 – Rochet2