Pairs less performant than other iterators?

I recently saw a post about using nothing instead of pairs in loops, I thought it would be a slow and/or deprecated method and wanted to try it myself. If the measurements are true, pairs is the worst iterator in terms of performance.

image

Is there a reason to this performance impact? Here is the test code:

local dictionary = {
	["aad"] = 4,
	["hello"] = "a",
	["yes"] = "no",
	[653] = 1,
}
local array = {"43242","aadf","tgergre","gfgegf"}
local Frequency = 10^7

print("\n\n\n\n")


c = os.clock()
for i = 1, Frequency do
	for i,v in ipairs(array) do
		local index = i
		local value = v
	end
end
print("Ipairs with array:		"..tostring(os.clock()-c))
print()


c = os.clock()
for i = 1, Frequency do
	for i,v in pairs(dictionary) do
		local index = i
		local value = v
	end
end
print("Pairs with dictionary:	"..tostring(os.clock()-c))


c = os.clock()
for i = 1, Frequency do
	for i,v in pairs(array) do
		local index = i
		local value = v
	end
end
print("Pairs with array:		"..tostring(os.clock()-c))
print()

c = os.clock()
for i = 1, Frequency do
	for i,v in next, dictionary do
		local index = i
		local value = v
	end
end
print("next with dictionary:	"..tostring(os.clock()-c))

c = os.clock()
for i = 1, Frequency do
	for i,v in next, array do
		local index = i
		local value = v
	end
end
print("next with array:		"..tostring(os.clock()-c))
print()

c = os.clock()
for i = 1, Frequency do
	for i,v in dictionary do
		local index = i
		local value = v
	end
end
print("Nothing with dictionary:"..tostring(os.clock()-c))

c = os.clock()
for i = 1, Frequency do
	for i,v in array do
		local index = i
		local value = v
	end
end
print("Nothing with array:		"..tostring(os.clock()-c))

Any information is appreciated

Edit: Forgor ipairs doesnt work with dictionaries, fixed a few mistakes

1 Like

I think that os.time() is a better way to measure performance impact with these sorts of things, though I think that tick() is pretty much the same. Honestly, other than this, I don’t know why pairs is so slow.

Oops, os.clock() is actually better, not os.time()

1 Like

I think you meant os.clock(), since os.time() returns integers. Nevermind, you edited your comment.

I agree that os.clock() is better, I replaced tick() with that and the results were like this:
image

Yeah, those results seem more accurate. Still takes up a surprising amount of performance. And why it takes up more with an array than it does with a dictionary is a mystery to me…

I don’t know if I’m going to go back and edit all my coding now, I didn’t realize that having nothing was actually faster. I’ve always used pairs.

2 Likes

I’ve also always used pairs and thought it just returned next. This might be a bug, but my rank isn’t enought to post in #bug-reports

Well, yeah. I already knew that ipairs was better than pairs, but not that having nothing was also better… this is a big surprise to me.

1 Like

ipairs is still the best for dictionaries, but it looks like nothing is better on arrays. I’ll mark this comment as the solution until someone more knowledged explains it

local dictionary = {
	["aad"] = 4,
	["hello"] = "a",
	["yes"] = "no",
	[653] = 1,
}


print("ipairs:")
for i,v in ipairs(dictionary) do
	print("\t",i,v)
end

print("pairs:")
for i,v in pairs(dictionary) do
	print("\t",i,v)
end

print("next:")
for i,v in next, dictionary do
	print("\t",i,v)
end

print("nothing:")
for i,v in dictionary do
	print("\t",i,v)
end

prints this:
image
Ipairs does not work with dictionaries.


Also with the next test you used the dictionary twice, not the array
image


Here are my results:
image
(which is fastest seems to change everytime I run it)

It’s still surprising that next and nothing are the fastest.

1 Like

These results seem much more believable than the first ones…

Has anyone actually had code where this made a huge difference? Normally it’s more about what happens inside of the loop instead of how I iterate so I just use pairs because I know it will work with any table

Yeah, I made a few errors in the test code and completely forgot ipairs doesn’t work with dictionaries. However nothing and next are still faster than pairs.

image

1 Like