Since there was this offtopic argument going on about performance of for-in versus for-to.
12 plus ones
Shared publicly•View activity
View 5 previous comments
- Short of handcoded assembly (or serious hacks) and a very optimized corner case I don't see that happening.
And thats more like the linked list I talked about this in the other thread. Things that normally arent indexed easily or dont index well (speed), generally dont with for..to loops anyway.27w
- I don't see it happening not even in .NET. There are several detailed comparisons out there. In real world, "for" is faster 99% of the times. In the other 1% "foreach" (or for in) can match the speed. This is an old one from Jon Skeet:27w
- http://cc.davelozinski.com/c-sharp/for-vs-foreach-vs-whileWe are comparing apples and oranges here - .NET, C# and JIT are generating amazingly well optimized code that Delphi can only dream of (yes, even though it compiles to native code! rolleyes) - anyway look at these results (which were posted in the comments of Jons article) -
Notice the difference between the for and foreach loop of the int array and his assumption: "I can only think that this is because it takes longer for a For loop to calculate and access a particular array index than it does a ForEach loop to assign the next value to allocated memory."
What does that mean?
Well the compiler can turn a foreach/for-in loop over an array into this:
p := @nums;
for i := 0 to High(nums) do
if p^ = 0 then;
If you measure that against
for i := 0 to High(nums) do
if nums[i] = 0 then;
You will see that the pointer shifting wins because it trades the second loop variable (still using the count to zero one) for a pointer.
Loops.dpr.87: if nums[i] = 0 then;
004DC975 8B45FC mov eax,[ebp-$04]
004DC978 833CB000 cmp dword ptr [eax+esi*4],$00
004DC97C 46 inc esi
Loops.dpr.86: for i := 0 to High(nums) do
004DC97D 4B dec ebx
004DC97E 75F5 jnz $004dc975
Loops.dpr.102: if p^ = 0 then;
004DCA2B 833800 cmp dword ptr [eax],$00
004DCA2E 83C004 add eax,$04
Loops.dpr.100: for i := 0 to High(nums) do
004DCA31 4B dec ebx
004DCA32 75F7 jnz $004dca2b
While having said that - I think a compiler could even turn a for-to loop into that...
But still these results tell nothing about real application performance - I have used the pointer shifting instead of index access before because in some microbenchmark it performed better but in some real code it had zero affect.27w
- I see several "suspicious" things in that article you have just posted:
1- His While loop is 2x faster (List), 4x faster (Dictionary) and 6x faster (DataTable) than a simple for (#loops = 100). Two things come to my mind: (a) his own code creates distortions or (b) .NET jit compiler is severely flawed and is unable to optimize a simple for loop like that, comparing to a while loop.
Given that I consider that (b) is not true, the only other viable explanation is (a). If you have other explanation for that, I'm all ears.
2- Unfortunately, his source code is broken and won't compile in VS 2017. There are dozens of errors (even after replacing < and > 's) and I don't have enough time to fix it right now, so it is actually impossible to determine myself if his data is correct (I ran Jon Skeet benchmark myself, which compiles just fine as is). Maybe that's the reason why there is not a single comment confirming/denying his findings... His code style, which reminds me something I did more than 30 years ago, doesn't make me want to spend time fixing it either.
3- Dictionaries are not intended to be accessed the way he does. Delphi's own generic TDictionary doesn't even allow that! Dictionary benchmark should just be ignored, IMO.
4- If you create a benchmark comparing arrays of simple types (int and double) and lists (I'll deliberately pretend Dictionaries were not included) and in the end you find out that foreach is faster when iterating through arrays and declare that foreach is faster in most cases, the conclusion is very likely to be wrong in real world applications. Arrays are not as versatile as lists and are not ideal for several common tasks in real world apps where lists are more likely to be used. PS: This also applies to Jon Skeet's benchmark.27w
- "While having said that - I think a compiler could even turn a for-to loop into that..."
Exactly. I don't see why that kind of optimization can't be applied in both cases.27w
- It would be nice if a for..in could return a typed pointer to an element instead of the value. I guess it can be faster in some cases, and it’ll allow you to change the value that it points to.
The compiler could switch to that behavior if the loop variable is a ^reference to the element type.27w
Add a comment...