I'm working on a game for the xbox360, using XNA. On the Xbox the garbage collector performs rather badly compared to the one on a PC, so keeping garbage generated to a minimum is vital for a smoothly performing game.
I remember reading once that calling a delegate creates garbage, but now for the life of me can't find any references to delegates creating garbage. Did I just make this up or are delegates messy?
If delegates are messy, bonus points for suggesting a workaround.
public delegate T GetValue<T>(T value, T[] args);
public static T Transaction<T>(GetValue<T> calculate, ref T value, params T[] args) where T : class
{
T newValue = calculate(value, args);
return foo(newValue);
}
My code looks vaguely like that at the moment, the only solution I can think of to rid myself of delegates is to pass in a class which inherits an interface IValueCalculator, and then I can call the method on that interface, that's not really very neat though!
Delegate creation generates garbage, as others already noted.
In your example, using
params
argument probably generates garbage as well.Consider providing overloads without using params keyword.
That is the reason why overloads with different number of arguments usually exist in library methods along with the one using
params
keyword:See String.Format Method (String, Object[])
Yes and no.
Calling simple delegate does not allocate any stuff on heap, but creating a delegate allocate 64 bytes on heap.
In order to avoid GC, you can precreate the delegate.
Let's verify it:
Benchmark:
The output following, scroll right to see Allocated Memory/Op column:
In the desktop environment garbage is effectively free. There what you want to worry about is how much non-garbage you are producing. Remember how the garbage collector works: it first marks all known objects, then it clears the mark on all live objects and compacts the live objects. The expensive step there is "unmark the live objects". Destroying the garbage is cheap; it's identifying the live objects that is expensive, and that cost depends on the number of live objects you have (and the complexity of their reference topology), not on the number of dead objects you have.
However, on XBOX and other compact frameworks, the garbage collector runs quite frequently and runs more often when new allocations are created, so yes, you are correct to worry about creating garbage too. You want to both keep the live set small (so as to make a collection cheap) and not make new allocations (because that triggers collections.)
Creating a delegate does allocate memory, but calling one is nothing more than calling a method named Invoke on a class. A delegate is not much more than a class with a method named Invoke that happens to immediately call another method when it is called.
Regardless, if you have a problem with memory performance then the right thing to do is to get out the memory profiler and use it to analyze your program. Casting about at random wondering if this or that happens to allocate memory is like trying to weed your garden with nail scissors; it takes a lot of time and doesn't actually accomplish your goals. Use a profiler to analyze your performance and see where the problems are, and then fix them.
A delegate is itself an object, so if you create a delegate, perhaps for an anonymous method, and give this to some other method to execute, and don't store the delegate for future reference, then yes, that will produce garbage.
For instance, this:
In this case, a new delegate object is created, but beyond the call to
ForEach
it is not referenced, and thus eligible for garbage collection.However, calling delegates does by itself not produce garbage, any more so than calling any other method of the same type would. For instance, if you call a delegate that takes an
Object
parameter, passing in anInt32
value, this value will be boxed, but that would happen if you called a normal method the same way as well.So using delegates should be fine, but excessive creation of delegate objects will be a problem.
Edit: A good article on memory management for Xbox and XNA is here: Managed Code Performance on Xbox 360 for XNA: Part 2 - GC and Tools. Pay attention to this quote:
As you can see, try to avoid creating lots of unnecessary objects, and you should fare better.