a6308d8378
The original theory was that preallocating the array forced lua to use the "array part" of a table instead of the "hash part", which should be faster since lookups are a simple linear offset calculation and not a hash with collision check. It turns out, however, that in empirical testing, whether the array-preallocated or the naive-allocated version is faster depends on circumstances, such as how sparse the array is, how uniform access is, or how much other load the system is under. This seems to suggest that arrays are more computationally-efficient but less cache-efficient, so cache evictions caused by other concurrent processes may slow this method down significantly. Worst-case performance will be the most noticeable here, since a system that's heavily loaded would have the most need for speed in the first place, so it's probably better generally to use the naive allocation. In all, the naive allocation method also seemed to be the least sensitive to external factors. In addition to the array method, attempts to pre-compile the dynamic checks into a binary tree of if/then statements (which could be JITted and optimized) failed as well.
72 lines
1.8 KiB
Lua
72 lines
1.8 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local error, ipairs, math, minetest, nodecore, pairs
|
|
= error, ipairs, math, minetest, nodecore, pairs
|
|
local math_floor
|
|
= math.floor
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local thickness = 128
|
|
|
|
nodecore.stratadata = nodecore.memoize(function()
|
|
local data = {}
|
|
data.stratbyid = {}
|
|
data.altsbyid = {}
|
|
for k, v in pairs(minetest.registered_nodes) do
|
|
if v.strata then
|
|
local sn
|
|
for s, n in ipairs(v.strata) do
|
|
if n == k then sn = s end
|
|
end
|
|
if not sn then error(k .. " not found in own strata") end
|
|
local cid = minetest.get_content_id(k)
|
|
data.stratbyid[cid] = sn
|
|
data.altsbyid[cid] = {}
|
|
for s, n in ipairs(v.strata) do
|
|
data.altsbyid[cid][s] = minetest.get_content_id(n)
|
|
end
|
|
end
|
|
end
|
|
return data
|
|
end)
|
|
|
|
nodecore.register_mapgen_shared({
|
|
label = "stone strata",
|
|
func = function(minp, maxp, area, data, _, _, _, rng)
|
|
if minp.y > -64 then return end
|
|
|
|
local ai = area.index
|
|
local t = nodecore.hard_stone_strata
|
|
local sd = nodecore.stratadata()
|
|
local byid = sd.stratbyid
|
|
local alts = sd.altsbyid
|
|
|
|
for z = minp.z, maxp.z do
|
|
for y = minp.y, maxp.y do
|
|
local raw = y / -thickness
|
|
local strat = math_floor(raw)
|
|
local dither = raw - strat
|
|
if strat > t then
|
|
strat = t
|
|
dither = nil
|
|
elseif dither > (4 / thickness) then
|
|
dither = nil
|
|
else
|
|
dither = (dither * thickness + 1) / 5
|
|
end
|
|
local offs = ai(area, 0, y, z)
|
|
for x = minp.x, maxp.x do
|
|
local i = offs + x
|
|
if byid[data[i]] then
|
|
if dither and rng() >= dither then
|
|
data[i] = alts[data[i]][strat]
|
|
else
|
|
data[i] = alts[data[i]][strat + 1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end,
|
|
priority = -100
|
|
})
|