How efficient is this raycast hit module script?

Please keep in mind that Help and Feedback > Code Review should not be used to discuss such negligible optimizations and that the review should be relevant to the topic at hand.

For the given code, pairs should be used, as premature optimizations are “the root of all evil”. This falls under said case.

Using next, table is by no means a representation of “good” production code.

Something many gloss over is that code must be maintained, reviewed, and augmented at a later date. “Good” code is something that can be universally understood, readable, and optimized for developer ergonomics with performance in mind, but not at the forefront of the designing process.

Premature optimizations are an anti-pattern, and should be avoided.

This is a universal pattern in programming at any layer of abstraction. Most language references, cookbooks, and handbooks–of any reputability–will advise against such a negligible optimization at the expense of the developer. This is no different for Lua, as the creator of the Lua language advises against these types of optimizations.

Tangent on for loop optimization

As a matter of fact, next, table is less performant than pairs or ipairs. This performance issue only existed for Lua JIT and, for some reason, most believe it is an issue global to all Lua code.

Also, most people don’t realize the benefit that ipairs gives you the index and value. When you incorporate a generic for loop that indexes the value, to be the same as ipairs, it is the least performant.

local array = {};

for index = 1, 1e5 do
	array[index] = true;
end

local startFor = tick();
for index = 1, #array do
	local value = array[index];
end
print("Generic for loop: ", tick() - startFor);

local startIpairs = tick();
for index, value in ipairs(array) do
	
end
print("for in ipairs loop", tick() - startIpairs);

local startPairs = tick();
for index, value in pairs(array) do

end
print("for in pairs loop", tick() - startPairs);

local startNext = tick();
for index, value in next, array do
	
end
print("for in next loop", tick() - startNext);

This, on average, shows in Luau (Roblox’s implementation of Lua):

Generic for loop: ~0.00072
For in ipairs loop: ~0.00044
For in pairs loop: ~0.00057
For in next, table loop: ~0.00069

It’s often a good practice to benchmark proposed optimizations in the rare chance you must perform them before implementation.


Conclusion

Do not optimize your code at such a negligible level to where it hurts your codebase’s maintainability and readability, as these are more important than whatever ‘optimizations’ you can squeeze in. This is the “professional” standpoint of things in any layer of abstraction in computer science as a study. Therefore, in this scope, disagreements about these optimizations are trivial and are a vacuum of time given that many, many people have already discussed this and come to the conclusion above.

@Procedurall’s code, under @BanTech’s advice, is performant and readable enough for production code. Until further notice, it should not be optimized unless realistic issues come of this, in which case it is not the design of this function, but the entirety of the project’s design that should be put into question.

Ergo:

“Premature optimizations are the root of all evil.”

2 Likes