Why does a local var reference cause a large performance degradation?

You're right that the code does about the same amount of work in either case.

But the garbage collector ends up doing very different things in the two cases.

In the str version, at most two string instances are alive at a given time. This means (almost) all new objects in generation 0 die, nothing needs to be promoted to generation 1. Since generation 1 isn't growing at all, the GC has no reason to attempt expensive "full collections".

In the str2 version, all the new string instances are alive. Objects get promoted to higher generations (which may involve moving them in memory). Also, since the higher generations are now growing, the GC will occasionally try run full collections.

Note that the .NET GC tends to take time linear to the number of live objects: live objects needs to be traversed and moved out of the way, while dead objects doesn't cost anything at all (they simply get overwritten the next time memory is allocated).

This means str is the best-case for garbage collector performance; while str2 is the worst-case.

Take a look at the GC performance counters for your program, I suspect you'll see very different results between the programs.


No, a local reference is not slow.

What is slow, is creating tons of new string instances, which are classes. While the fast version reuses the same instance. This also can be optimized away, while the constructor call can not.