6

I am writing a game using C# and have found a number of cases where a function takes a delegate and I have inadvertently passed in a function name instead of creating and caching a delegate to use as the parameter instead. This causes a delegate object to be created for each call to these functions, which then immediately becomes garbage when the function returns.

I'd like to find all the places where I've made this mistake, and I'd prefer to avoid reading every line of every file looking for them (there are years worth of code). I saw how VB has an 'option strict' which will disable implicit construction of objects which I think would work for me if C# had that feature, but I don't think it does. I've also reviewed compiler warning options and none of them seem to help here either.

Is there any reasonably convenient way to identify these objects created by implicit delegate inference so I can find out where I need to create/cache the callbacks to avoid the garbage?

Eric Cosky
  • 554
  • 3
  • 11
  • 1
    Is there some code examples you can provide where, for example, a Visual Studio regex search might find them? – mellamokb Apr 25 '12 at 18:20
  • Only way I see if find the method/function that accepts a delegate then right-click->find references (though this involves manually checking each call). – Brad Christie Apr 25 '12 at 18:21
  • 1
    Do you have any evidence that this is *actually* causing you a problem? I'd expect that for the vast majority of the time, the performance downside is negligible compared with the readability benefit of using a method group conversion instead of explicit caching. – Jon Skeet Apr 25 '12 at 18:22
  • 5
    @JonSkeet: I share your sentiment Jon, but I note that games are a special case. The garbage collector in the XBOX version of the CLR is notoriously sensitive to garbage creation, so game developers often have to seek out and eliminate all sources of garbage creation in their game loops. – Eric Lippert Apr 25 '12 at 18:28
  • @EricLippert: Ah, I haven't noticed the game part. Yes, that could well make a difference. I think I'd still try to isolate "the bits that matter" vs (say) menu handling. – Jon Skeet Apr 25 '12 at 18:29
  • @mellamokb - Code examples wouldn't be helpful I'm afraid, I have quite a few named delegate types. – Eric Cosky Apr 25 '12 at 18:30
  • 1
    @Jon Skeet - Yes, I first noticed this when doing memory profiling and a high frequency function down in some physics code was creating thousands of these a frame, ultimately responsible for generating enough objects to trigger GC every 5 seconds or so which is has an unacceptable impact on framerate. – Eric Cosky Apr 25 '12 at 18:32
  • @Eric Lippert - You are spot on, I am using XBOX and an unfortunately large amount of time & effort is required to keep garbage generation to an absolute minimum. GC doesn't have much impact on the PC, but on the XBOX it can mean stuttering gameplay with framerate drops down to as low as 5hz. There really is no choice but to do everything possible to eliminate as much garbage as possible. – Eric Cosky Apr 25 '12 at 18:35
  • You can still use delegate inference when you set your cache variable. So this is not a problem of which syntax you use, but a problem of creating too many instances instead of reusing one. So maybe you should also search for delegate instantiations with the `new` keyword (like `new MyDelegateType(MethodGroupName)`), to see if they need caching. – Jeppe Stig Nielsen Apr 25 '12 at 18:53
  • @Jeppe Stig Nielsen - Yes, exactly. I use inference to create the cached versions that are used repeatedly. Regarding searching, I have almost always used inference in this codebase so searching for new delegate by type is impractical. – Eric Cosky Apr 25 '12 at 18:57

1 Answers1

10

In short, your question is "how can I find all method group conversions?"

We are at present working on a project code-named Roslyn which will allow you to use the same semantic analysis engine that the C# compiler and IDE uses. It will expose the syntactic model of the language, and then provide a semantic analysis API by which you can ask questions of the semantic analyzer.

With Roslyn you could compile all your code into syntax trees and then search those syntax trees for every expression. There will be an API that allows you to determine whether the expression was converted to anything, and if so, how the conversion analyzer classified the conversion.

We are at present in the "community technology preview" stage; we have a preliminary implementation but it is nowhere near fully featured yet. I do not remember if the method group conversion analyzer was implemented in the CTP release or not.

Give it a try, and if you have feedback about it we would love to hear your thoughts on the Roslyn forum.

Details here:

http://msdn.microsoft.com/en-us/roslyn

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Thanks, I've been looking forward to the Roslyn project for a number of reasons, I'll add this to the list of things to check out when I am able to spend some time with it. – Eric Cosky Apr 25 '12 at 18:45