Оптимизация обычно нужна когда модули на Lua неэффективны и выполняются слишком долго.
Важное примечание[]
"Мы должны забыть о мелких оптимизациях на 97% нашего времени. Преждевременная оптимизация — корень всех зол." [1]
Основные советы[]
Если ваши модули по каким либо причинам превышают лимиты, вы должны провести оптимизацию.
Когда это возможно[2]:
- Используйте локальные функции и переменные
- Избегайте вложенных функций
- Используйте массивы вместо таблиц (хеш-таблицы)
- Используйте локальные переменные вместо индексирования таблиц
Простая оптимизация, такая как копирование глобальных функций (например string.match) может намного сильнее улучить производительность.
Совет: используйте os.clock() для замеров производительности (запишите в переменные время до и после выполнения функции, а затем вычтите начало из конца).
Конкатенация строк против конкатенации таблиц[]
Когда вы работаете с соединением большого количества строк, то будет намного эффективнее добавить их в массив, а затем использовать table.concat, вместо соединения их "в ручную"[3].
-- Это медленнее
local people = {"John", "Mary", "Parker", "Sue", "Anonymous", "..."}
local text = ""
for i = 1, #people do
if i > 1 then
text = text .. ", "
end
text = text .. people[i]
end
print(text)
-- Это быстрее
local people = {"John", "Mary", "Parker", "Sue", "Anonymous", "..."}
local text = table.concat(people, ", ")
print(text)
Использование таблиц для сравнений[]
Вместо огромной кучи сравнений в операторе if, можно создать сет с этими значениями[4]. Например: это типичная структура с оператором if:
local function foo(value)
if value == "foo" or value == "bar" or value == "baz" or value == "qux"
or value == "lorem" or value == "ipsum" then
return "что-то"
end
return "что-то другое"
end
...а это более эффективный способ сравнения, основаный на таблицах:
local function foo(value)
local validValues = {
foo = true,
bar = true,
baz = true,
qux = true,
lorem = true,
ipsum = true
}
if validValues[value] then
return "что-то"
end
return "что-то другое"
end
Примечание: вы можете использовать любые значения "истина", а не только true.
Шаблоны[]
Использование большого кол-ва шаблонов на одной странице — одна из главных проблем, которая влияет на производительность модулей. Каждый вызов приближает вас к лимитам.
Есть несколько методов исправить это:
- Консолидация — перенести весь код в модуль и вызывать его меньше раз
- Переписать код, чтобы он был более эффективным
Переделка "базы данных" шаблонов в модули данных[]
Создание базы данных шаблонов может создавать множество проблем, особенно если они основаны на функциях парсера. Одной из идей может быть создания модуля с ними, что описано в статье "Wikitext migration".
Если шаблон используется несколько раз на странице, используйте mw.loadData вместо require:
local data = mw.loadData("Модуль:Мои данные")
return data[frame.args[1]]
Избегайте множества вызовов одного и того же модуля[]
Вместо этого примера:
local p = {}
function p.showpopulation(frame)
local pop = {['Китай'] = 50, ['Австралия'] = 20, ['Гана'] = 10}
return pop[frame.args[1]]
end
return p
{{#invoke:Мой_модуль|showpopulation|Китай}}
{{#invoke:Мой_модуль|showpopulation|Австралия}}
{{#invoke:Мой_модуль|showpopulation|Гана}}
Сделайте следующее:
local p = {}
function p.showpopulation(frame)
local pop = {['Китай'] = 50, ['Австралия'] = 20, ['Гана'] = 10}
local args = frame.args
return pop[args[1]] .." ".. (pop[args[2]] or "") .. " " ..(pop[args[3]] or "")
end
return p
{{#invoke:Мой_модуль|showpopulation
|Китай
|Австралия
|Гана
}}
Примечания[]
- ↑ The fallacy of premature optimization http://ubiquity.acm.org/article.cfm?id=1513451
- ↑ http://www.lua.org/gems/sample.pdf
- ↑ http://www.lua.org/pil/11.6.html
- ↑ http://stackoverflow.com/a/12865406