Я вижу три направления оптимизации:
Оптимизация процесса взаимодействия с системой.
Я не уверен, что это возможно в рамках имеющегося техзадания, но надо попытаться это сделать, т.к. именно оптимизация процесса даёт максимальный эффект.
Оптимизировать работу с полный хаосом невозможно. Поэтому надо постараться максимально упорядочить работу своей системы, добавив какие-то правила взаимодействия с ней. Например, можно разрешить доступ игроков к единственному сундуку, а с остальными сундуками взаимодействовать исключительно через транспозеры. Такое решение снизит масштаб неопределённости. В общем, нужно упорядочить хаос.
Оптимизация взаимодействия с периферией
Количество запросов к периферии в этой программе не велико, но сами запросы обрабатываются крайне медленно. Поэтом они вносят значительный вклад в общее время выполнения программы. Главное правило работы с периферией — ограничить количество запросов к ней.
В этой программе я вижу вызов getInventoryName и следом за ним getAllStacks. На выполнение каждого из этих запросов требуется по одному такту времени. Но зададим вопрос: какова роль каждого из этих запросов, и можно ли избавиться от какого-нибудь из них. Например, является ли необходимым вызов getInventoryName в каждом цикле? Может быть, достаточно однократной проверки при старте программы? Если так, то мы уменьшим частоту обращений к периферии в два раза. Но можно пойти ещё дальше. Роль вызова getInventoryName заключается лишь в том, чтобы оценить возможность вызова getAllStacksбез возникновения ошибки. Но зачем нужна эта проверка, если ошибку можно обработать по результату выполнения getAllStacks?
Оптимизация обработки данных
Тут основные правила: избегать повторной обработки уже обработанных данных и отдавать предпочтение более эффективным конструкциям.
В этой программе я вижу циклический перебор всех предметов во всех инвентарях и полный перебор общий таблицы для каждого из предметов. Очевидно, такой алгоритм обработки неэффективен:
local this = false
for g,allItm in pairs(allItems) do
if ((this==false) and (allItm.name == thisItm.name) and (allItm.label == thisItm.label)) then
this = true
allItm.count = allItm.count+thisItm.size
end
end
if this == false then
table.insert(allItems, {name = thisItm.name, count = thisItm.size, label = thisItm.label})
end
Если работы с длинными циклами не избежать, то цикл надо останавливать сразу же, как достигнута цель. Для этого в Lua существует ключевое слово break. Заодно избавляемся от лишней проверки переменной this.
for g,allItm in pairs(allItems) do
if allItm.name==thisItm.name and allItm.label==thisItm.label then
this = true
allItm.count = allItm.count+thisItm.size
break
end
end
Но и этот цикл также работает слишком медленно. Полностью избавиться от цикла помогут ассоциативные свойства таблиц Lua. Для этого потребуется изменить структуру таблиц и обращаться к их элементам не по индексам, а по строковым идентификаторам. Учитывая, что в программе поиск осуществляется по строкам thisItm.name и thisItm.label, ключом к элементам таблиц может быть объединённая строка thisItm.name..thisItm.label. В этом случае код упростится:
local key = thisItm.name .. thisItm.label
if allItems[key] then
allItems[key].count = allItems[key].count + thisItm.size
else
allItems[key] = {name = thisItm.name, count = thisItm.size, label = thisItm.label}
end
Пожалуй, я перечислил все основные способы оптимизации этой программы, дающие максимальный эффект и не снижающие читаемость кода.