Jest to spowodowane zwiększeniem rozmiaru/ponownego obciążenia stołu. Kiedy tabela jest tworzona, jest pusta. Po wstawieniu elementu następuje ponowne uruchomienie, a rozmiar tabeli wzrasta do 1. To samo dzieje się po wstawieniu innego elementu. Reguła jest taka, że tabela jest uprawiana, gdy brakuje miejsca (w tablicy lub części hash), aby pomieścić inny element. Nowy rozmiar to najmniejsza potęga 2, która może pomieścić wymaganą liczbę elementów. Na przykład. rehash pojawia się po wstawieniu elementu, jeśli tabela zawiera elementy 0, 1, 2, 4, 8 itd.
Technika, którą opisujesz, zapisuje te rehy, ponieważ Lua nie zmniejsza tabel. Więc jeśli masz częste operacje wypełniania/spłukiwania, lepiej jest (zgodnie z wydajnością) robić to tak, jak w twoim przykładzie, niż tworzyć pustą tabelę.
Aktualizacja:
mam postawić mały test:
local function rehash1(el, loops)
local table = {}
for i = 1, loops do
for j = 1, el do
table[j] = j
end
for k in ipairs(table) do table[k] = nil end
end
end
local function rehash2(el, loops)
for i = 1, loops do
local table = {}
for j = 1, el do
table[j] = j
end
end
end
local function test(elements, loops)
local time = os.time();
rehash1(elements, loops);
local time1 = os.time();
rehash2(elements, loops);
local time2 = os.time();
print("Time nils: ", tostring(time1 - time), "\n");
print("Time empty: ", tostring(time2 - time1), "\n");
end
Wyniki rzucić ciekawe. Uruchomienie test(4, 10000000)
na Lua 5.1 dało 7 sekund dla nils i 10 sekund dla opróżnień. W przypadku stołów większych niż 32 elementy pusta wersja była szybsza (im większy stół, tym większa różnica). test(128, 400000)
dał 9 sekund dla nils i 5 sekund dla opróżnień.
Teraz na LuaJIT, gdzie operacje przydziału i gc są stosunkowo powolne, uruchomienie test(1024, 1000000)
dało 3 sekundy dla nils i 7 sekund dla opróżnień.
P.S. Zwróć uwagę na różnice w wydajności między zwykłymi Lua i LuaJIT. W przypadku 1024-elementowych tabel, zwykły Lua wykonał 100 000 testowych iteracji w około 20 sekund, LuaJIT wykonał 1 000 000 iteracji przez 10 sekund!
Aby zmniejszyć alokację pamięci - operacje dealokacji? –
Oprócz problemów z wydajnością opisanych w odpowiedzi ... jeśli tabela jest używana przez inne części programu pod innymi nazwami, pętla jest absolutnie niezbędna. Jeśli wykonasz zadanie, po prostu stracisz połączenie z obiektem tabeli, a pozostałe nazwy nadal wskazują na tę samą pełną tabelę, podczas gdy pętla usuwa ją dla wszystkich. –