0

I'm currently looking into a way of replacing all foreach loops with for loops in order to see the if I could gain some minor benefits in some legacy code that creates a ton of garbage.

The thing is that it would take days to change all by hand in order to measure if the garbage removed would impact the performance in a bad way instead, so I scripted a parser for making a simple swap. The thing is that some cases uses list others arrays and some ienumerable. So the question I have is, can I read a c# file from another project and evaluate the type of container used to switch iteration programmatically instead to save time?

Even if it's a bad idea it would be a fun experiment to try and automate something like this.

  • 9
    Let me save you some trouble: you will not gain any benefits with your proposed change. Many collection classes can be efficiently accessed with foreach but are considerably slower with indexed access, such as any linked list type. Anyways, "is it possible" questions make poor questions. – whatsisname Mar 29 '17 at 5:33
  • It does seem a bad idea. For can be a bit faster in loops with little iterations (no enumerator needs to be setup and used) but I do not expect much difference in garbage production. Foreach is safer to use, looks better and is easier to maintain. If you really want to know the impact on garbage production, create a test program with some nested loops and compare the different approaches. As for the "fun" part: you have to replace the iterator with an indexed property using a likely unique name for the new integer iterator and generate an assignment as the first line in your new loop. – Martin Maat Mar 29 '17 at 5:41
  • I've made some tests and a nested foreach vill generate 40B of garbage each time it ends. So if I iterate over 1000 objects I'll get garbage equal to 40 000B. Regular for gets 0. – Tartarus Mar 29 '17 at 5:50
  • 1
    Have you profiled your application? Is this your bottleneck? – RvdK Mar 29 '17 at 8:26
  • It's one of the problems, If it was possible to make a quick change I would look into it further. But as mentioned it's probably a bad idea and will take to much time to do by hand. – Tartarus Mar 29 '17 at 10:21
0

One idea is to insert a line of code before each foreach loop which assigns the container to an IList without cast. If the compiler cannot deduce that the assignment must succeed at compile-time, that means you cannot safely replace that with a for, because the container may not support retrieval of items by integer index. IList is guaranteed to support support retrieval of items by integer index.

Do not try to be smart and make it a cast. The cast may compile, but it may fail at run time. That means you either keep the original code, or you must generate new code that handles this situation and do something else (basically executing the original foreach code or a while loop on IEnumerator.)

In this way, you will need to insert one line of code at a time, perform a trial compilation of the project, revert the code change, then apply the desired code change depending on the IList compatibility.

I haven't tested this idea and I cannot predict whether this will work.

  • I kind of did this earlier but without the recompile, I guess if I added that I would have to make fewer changes by hand afterwards and it may be a good enough quick test to see if i get less garbage but pay with performance. – Tartarus Mar 29 '17 at 10:33
3

This will almost certainly not solve you performance problems. So unless you are doing this purely for fun, you should use profiling to investigate the actual reasons.

But taking the question: It is possible, but not easy to do. Say you have code like this:

var x = SomeClass.SomeMetod(a);
foreach (var item in x) { ... }

To know if x is an array, a parser is not enough. You will have to perform a full compilation of the project to resolve its type. The only realistic way is to use something like Roslyn to perform a parse and full type resolution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.