Why is this for next loop slower?

So, tables in Lua are made out of two parts, arrays and hash tables. I’m thinking of only iterating over hash tables and used this code:

local length = #aTable
for i, v in next, aTable, length do
	-- do stuff
end

This code runs many times so it must be very performant. However, I noticed this code ran significantly slower than using this code:

local length = #aTable
for i, v in next, aTable do
	if i > length then
		-- do stuff
	end
end

Why is this so? I would expect the former code to run faster since it doesn’t have to iterate through the array part of the table yet it runs slower than the one that iterates over both parts of the table and does an if statement on top of that. Can anyone explain?
Btw, the tables uses positive integers as keys and the values stored in them are also positive integers if anyone is wondering.
The length of the array part of the tables ranges from 1024 to 1280. The number of tables I have are 8321.

In the second code sample, i will always be less than or equal to length, meaning the stuff is never done in any of the iterations.

Yea but in both for loops, I put no stuff in there so that I can get the actual performance review.

I don’t know anything how Luau is optimized internally but do you have a test case, example or any evidence that the second section of code is faster/slower than the first section?

I can’t reproduce that the second section of the code is faster:

local aTable = table.create(8320, 1280)
table.insert(aTable, 1, 1024)
do
	local length = #aTable
	local a = os.clock()
	for _ = 1, 100 do
		for i, v in next, aTable, length do
			_ = math.random()
		end
	end
	print(os.clock() - a)
end
do
	local length = #aTable
	local a = os.clock()
	for _ = 1, 100 do
		for i, v in next, aTable do
			if i > length then
				_ = math.random()
			end
		end
	end
	print(os.clock() - a)
end

0.00070400000004156
0.0097845000000234

3 Likes

If you’re not actually running any code then the difference in performance would be negligible and maybe random.

Ok imma prepare a quick test place brb.

Most likely the reason why the second loop is slower is because the code has to go another line before the loop starts, which is i > length, instead of just having to go through one line with “ATable, length”

1 Like

@Blockzez I think you’re getting that result because your array part is much larger than your hash part. It sounds like OP has a pretty mixed table that he’s testing with.

Yeah, this is mostly true. The way I was measuring my time was using while wait and tick(). When I removed wait and used os.clock(), the first code ran faster than the second code most of the time (the difference being random and negligible as you mentioned). I guess my problem is that when I used while wait, it made using the first code always take noticeable longer (up to a second!) and I don’t know why that’s the case.

I guess I should search for other ways to loop through tables without relying on wait but also not doing them all at once (as that might cause a script exhaustion moment). In the meantime, I will use the second code since while wait prefers that more for some reason.

Sorry everyone, I should had tested with os.clock before posting on the devforums.