Перейти к содержимому
  • 0
chanmagomed

Оптимизация работы с "Transposer" и таблицами

Вопрос

Добрый день, Я пишу выдавальщик предметов с огромного кол-ва слотов, сейчас программа работает медлеено и я ищу способы для ускорения работы с транспозерами и таблицами

сейчас у меня 4 транспозера с четырьмя сундуками на каждом.

В каждом сундуке по 117 слотов и в общем 1872 ячейки в системе.

при запуске программы, после выполнения поиска и после выдачи предмета выполняется этот код:

function chest.getStorageItems()
	local tpTable = {}
	local thisItems = {}
	local allItems = {}
	for k in component.list("transposer") do table.insert(tpTable,k) end
	for index, tp in pairs(tpTable) do
		for i=0,5,1 do
			if (component.invoke(tp, "getInventoryName", i)) and (i~=5) then
				
				thisItems = component.invoke(tp, "getAllStacks", i).getAll()
				for o,thisItm in pairs(thisItems) do
					if (thisItm.name~="minecraft:air") then
						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
						
					end
				end
				
			end
				
		end
	end
	return allItems
end

Сверху идёт провод, а выдача происходит на север.

Каждый раз проверять сундуки надо потому что поставка предметов идёт не через систему и во время работы программы нужный предмет может появиться.

Это обновление сейчас занимает 2-3 секунды, можно ли как-то ускорить этот процесс?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Рекомендуемые сообщения

Я вижу три направления оптимизации:

 

Оптимизация процесса взаимодействия с системой.

Я не уверен, что это возможно в рамках имеющегося техзадания, но надо попытаться это сделать, т.к. именно оптимизация процесса даёт максимальный эффект.

1 час назад, chanmagomed сказал:

Каждый раз проверять сундуки надо потому что поставка предметов идёт не через систему и во время работы программы нужный предмет может появиться.

Оптимизировать работу с полный хаосом невозможно. Поэтому надо постараться максимально упорядочить работу своей системы, добавив какие-то правила взаимодействия с ней. Например, можно разрешить доступ игроков к единственному сундуку, а с остальными сундуками взаимодействовать исключительно через транспозеры. Такое решение снизит масштаб неопределённости. В общем, нужно упорядочить хаос.

 

Оптимизация взаимодействия с периферией

Количество запросов к периферии в этой программе не велико, но сами запросы обрабатываются крайне медленно. Поэтом они вносят значительный вклад в общее время выполнения программы. Главное правило работы с периферией — ограничить количество запросов к ней.

 

В этой программе я вижу вызов 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

 

Пожалуй, я перечислил все основные способы оптимизации этой программы, дающие максимальный эффект и не снижающие читаемость кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поддержка на этом форуме лучше чем у платных поддержек разного софта))

Большое спасибо, это правда хороший ответ, который помимо рыбы даёт ещё и удочку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, chanmagomed сказал:

Поддержка на этом форуме лучше чем у платных поддержек разного софта))

Большое спасибо, это правда хороший ответ, который помимо рыбы даёт ещё и удочку.

Спасибо за высокую оценку. Я тоже рад нашему общению.

 

Хороший ответ почти всегда является следствием хорошего вопроса. Имеется, конечно, и значительный элемент удачи, но шансы сильно зависят от качества формулировки. А по формулировке этого вопроса можно гайд написать. Новичкам рекомендую брать пример.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...