I sat in a talk recently on performance with .NET applications. The speaker was suggesting things that I here others say often but I strongly disagree with. Two specific issues were the recommendation to use ngen and to never include debug info in release builds to achieve the best performance. The conversation went something like this:
I pressed him on the ngen:
Me: I thought one of the reasons you shouldn’t ngen is because the JIT compiler can do optimizations that result in superior runtime performance over ngen?
Him: Well, yes that is true
Me: So if you really care about perf, you shouldn’t ngen?
Him: Yes, but if you ngen you dramatically improve the start up time for the app
Me For the first time the app is run only, right?
Him: Well, yeah….
Me: And, there are load time effects that ngen can have (rebasing) that can actually result in worse load time perf?
Him: Well, yeah…
Then the debug info in release mode:
Him: You should definitely avoid putting debug info in your release builds
Me: So what is the impact if you do?
Him: Well, a couple extra instructions per method call
Me: So do you think an extra couple instructions actually has an impact on the overall perf of most apps? Aren’t they usually IO bound or have other perf bottlenecks that really form the performance limit for most apps?
Why don’t people get this? I’m not saying you shouldn’t always consider perf or that you should do stupid things that will affect perf. But if you are doing things that affect the maintainability of your system, I would always favor doing the things that result in more maintainable systems. Then address perf where needed. If your performance is already adequate, then you don’t have a problem. If it is not, it is probably due to one or a couple hot spots in your application that you can do some optimization on to get things back in check.
Ngen can either help or hurt perf, and can result in unpredictable results if anything in your system changes with respect to what version gets used. Me, I like deterministic systems. Debug info in your release builds can give you additional insight when errors happen in the production environment including line numbers in exceptions and additional ways to debug.
A lot of it has to do with good architecture and design too. Most often people apply performance tweaks liberally because they have no idea where the hot spots might be in their app or how to find them.
I just get frustrated when people latch onto a concept and apply it blindly without understanding when/where it is actually needed. Let’s face it, if a couple extra instructions per method call is really driving the performance of your entire application, you either write some incredibly tight code, or your app is a simple little test app that you created to drive home your point that doesn’t go out and make any DB queries, network calls, access the disk, or any of the other things that really drive the perf of real world apps.