views:

2368

answers:

17
+12  Q: 

Speeding Up C#

This is really two questions, but they are so similar, and to keep it simple, I figured I'd just roll them together:

  • Firstly: Given an established C# project, what are some decent ways to speed it up beyond just plain in-code optimization?

  • Secondly: When writing a program from scratch in C#, what are some good ways to greatly improve performance?

Please stay away from general optimization techniques unless they are C# specific.

This has previously been asked for Python, Perl, and Java.

A: 

NGEN will help with some code, but do not bank on it.

Personally, if your design is bad/slow, there is not much you can do.

The best suggestion in such a case, is to implement some form of caching of expensive tasks.

leppie
ngen may make a .NET program start up more quickly, but it can hurt post-startup performance (it doesn't optimize quite as aggressively).
Jon Skeet
Hence why I said not to bank on it. :)
leppie
But the important point is that if you're talking about non-startup performance, ngen won't help at all.
Jon Skeet
It all depends on the scenario. In my case (with IronScheme), I definitely get a speed up (not much) during runtime.Where NGEN shines, is with static/constant data (which consists roughly of 25% of my code).
leppie
Hmm... it's not clear to me how that happens, given that NGEN is basically just turning JIT into AOT. What do you believe NGEN is doing with your static/constant data that improves the runtime efficiency over JITting?
Jon Skeet
+2  A: 

A lot of slowness is related to database access. Make your database queries efficient and you'll do a lot for your app.

Joel Coehoorn
+14  A: 

Off the top of my head:

  • Replace non-generic variants of container classes by their generic counterparts
  • Cut down on boxing/unboxing. Specifically, use generics where possible and generally avoid passing value types as object.
  • For dialogs using many dynamic controls: suspend drawing until after inserting all controls by using SuspendLayout/ResumeLayout. This helps especially when using layout containers.
Konrad Rudolph
+8  A: 

One simple thing is to ensure that your build configuration is set to "Release". This will enable optimizations and eliminate debugging information, making your executable smaller.

More info on MSDN if needed.

Ben Hoffstein
A: 

Hi, I recomend you those books:

Effective C#.

More Effective C#

lluismontero
A: 

Don't use to much reflection.

chrissie1
+8  A: 

Unfortunately, relatively few optimisations are language specific. The basics apply across languages:

  • Measure performance against realistic loads
  • Have clearly-defined goals to guide you
  • Use a good profiler
  • Optimise architecture/design relatively early
  • Only micro-optimise when you've got a proven problem

When you've absolutely proved you need to micro-optimise, the profiler tends to make it obvious what to look for - things like avoiding boxing and virtual calls.

Oh, one thing I can think of which is .NET-specific: if you need to make a call frequently and are currently using reflection, convert those calls into delegates.

EDIT: The other answers suggesting using generics and StringBuilder etc are of course correct. I (probably wrongly) assumed that those optimisations were too "obvious" ;)

Jon Skeet
@your edit: I think it's good not to repeat too many pieces of advise. The real answer to a question is often the set of all answers combined.
Konrad Rudolph
+2  A: 
  • Use StringBuilder rather than lots of string concatenation. String objects are atomic, and any modification (appending, to-upper, padding, etc) actually generate a completely new string object rather than modifying the original. Each new string must be allocated and eventually garbage collected.

  • A generalization of the prior statement: Try to reuse objects rather than creating lots and lots of them. Allocation and garbage collection may be easy to do, but they hit your performance.

  • Be sure to use the provided Microsoft libraries for most things. The classes provided by the Framework often use features that are unavailable or difficult to access from your own C# code (i.e. making calls out to the native Windows API). The built-in libraries are not always the most efficient, but more often than not.

  • Writing asynchronous apps has never been easier. Look into things like the BackgroundWorker class.

  • Try not to define Structs unless you really need them. Class instance variables each hold a reference to the actual instance, while struct instance variables each hold a separate copy.

Jeff B
I think you mean immutable instead of atomic when describing strings.
Jon Skeet
String concatenation is actually fastest up until about 7 strings or so.
endian
Strings are also handled slightly differently by the runtime. They are cached (Interned), so that if two string instances are declared with the same value, the second instance will reuse the value of the first.
StingyJack
A: 

Use Ngen.exe (Should come shipped with Visual Studio.)

http://msdn.microsoft.com/en-us/library/6t9t5wcf(VS.80).aspx

The Native Image Generator (Ngen.exe) is a tool that improves the performance of managed applications. Ngen.exe creates native images, which are files containing compiled processor-specific machine code, and installs them into the native image cache on the local computer. The runtime can use native images from the cache instead using the just-in-time (JIT) compiler to compile the original assembly.

Gary Willoughby
As mentioned elsewhere, however, ngen only boosts startup performance - it doesn't generate better-optimised code. (Quite the reverse in some cases, in fact.)
Jon Skeet
A: 

In addition to the coding best practices listed above including using StringBuilders when appropriate and items of that nature.

I highly recommend using a code profiling tool such as ANTs Profiler by RedGate. I have found that after taking the standard steps for optimization that using Profiler I can further optimize my code by quickly identifying the area(s) of code that are most heavily hit by the application.

Mitchel Sellers
+3  A: 

Use composition instead of inheritance, limit boxing/unboxing, use generic collections, use foreach loops instead of for{} with a counter, and release resources with the standard Dispose pattern.

These are covered in detail in the excellent book Effective C#.

Robert S.
Although I generally use foreach instead of for, but for the ease of use, not performance. Do you know why exactly for is slower then foreach?
borisCallens
Since I posted this answer a few months ago, there was a question asked about foreach vs. for. I'll see if I can find it.
Robert S.
Or even better, More Effective C#
Ray Booysen
+2  A: 

Profile your code. Then you can at least have an understanding of where you can improve. Without profiling you are shooting in the dark...

Tim
+5  A: 

Use a decent quality profiler and determine where your bottlenecks are.

Then start asking how to improve performance.

Anyone who makes any blanket statements like 'avoid reflection' without understanding both your performance profile and your problem domain should be shot (or at least reeducated). And given the size of the .Net landscape it's pretty much meaningless to talk about C# optimization: are we talking about WinForms, ASP.Net, BizTalk, Workflow, SQL-CLR? Without the context even general guidelines may be at best a waste of time.

Consider also what you mean by 'speed it up' and 'improve performance'. Do you mean greater resource efficiency, or lower perceived wait time for an end user (assuming there is one)? These are very different problems to solve.

Given the forum I feel obliged to point out that there some quite good coverage on these topics in Code Complete. Not C# specific mind. But that's a good thing. Bear in mind the language-specific micro-optimisations might well be subsumed into the next version of whatever compiler you're using, And if the difference between for and foreach is a big deal to you you're probably writing C++ anyway, right?

[I liked RedGate's ANTS Profiler, but I think it could be bettered]

With that out the way, some thoughts:

  • Use type(SomeType) in preference to instance.GetType() when possible
  • Use foreach in preference to for
  • Avoid boxing
  • Up to (I think) 3 strings it's ok to do StringA + StringB + StringC. After that you should use a StringBuilder
piers7
Some people will tell you up to 5 strings before stringbuilder. Good post either way.
Echostorm
+1. Absolutely correct in emphasising how pointless blanket optimisation recommendations are, and how you ABSOLUTELY MUST PROFILE!
NM
Also nice to see a bit more sane StringBuilder recommendation. More often then not the stringbuilder is wrongly recommended for all situations.
borisCallens
I think just using StringBuilder gets you into the habit of always using it.
Jack Marchetti
A: 

This is true for any language, not just C#

  1. For an existing app, don't do anything until you know what's making it slow. IMHO, this is the best way.

  2. For new apps, the problem is how programmers are taught. They are taught to make mountains out of molehills. After you've optimized a few apps using this you will be familiar with the problem of what I call "galloping generality" - layer upon layer of "abstraction", rather than simply asking what the problem requires. The best you can hope for is to run along after them, telling them what the performance problems are that they've just put in, so they can take them out as they go along.

Mike Dunlavey
A: 

For Windows Forms on XP and Vista: Turn double buffering on across the board. It does cause transparency issues, so you would definitely want to test the UI:

protected override System.Windows.Forms.CreateParams CreateParams { 
    get { 
        CreateParams cp = base.CreateParams; 
        cp.ExStyle = cp.ExStyle | 0x2000000; 
        return cp; 
    } 
}
Lurker Indeed
A: 

I have the following MSDN article bookmarked, and find it to be a good general reference.

Improving .NET application pefformance

Winston Smith
A: 

Caching items that result from a query:

private Item _myResult;
public Item Result
{
     get
     {
          if (_myResult == null)
          {
               _myResult = Database.DoQueryForResult();
          }
          return _myResult;
     }
}

Its a basic technique that is frequently overlooked by starting programmers, and one of the EASIEST ways to improve performance in an application.

Answer ported from a question that was ruled a dupe of this one.

GWLlosa