Speeding Up C#

16,467

Solution 1

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.

Solution 2

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" ;)

Solution 3

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.

Solution 4

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

Solution 5

  • 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.

Share:
16,467
akdom
Author by

akdom

I've done a few things over the years: sysadmin work for a small non-profit, a few years interning at Red Hat, 5+ at Google, some teaching, a couple talks, a couple startup projects. Doing my own thing at the moment.

Updated on June 17, 2022

Comments

  • akdom
    akdom about 2 years

    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.

  • Jon Skeet
    Jon Skeet over 15 years
    ngen may make a .NET program start up more quickly, but it can hurt post-startup performance (it doesn't optimize quite as aggressively).
  • leppie
    leppie over 15 years
    Hence why I said not to bank on it. :)
  • Jon Skeet
    Jon Skeet over 15 years
    But the important point is that if you're talking about non-startup performance, ngen won't help at all.
  • Jon Skeet
    Jon Skeet over 15 years
    As mentioned elsewhere, however, ngen only boosts startup performance - it doesn't generate better-optimised code. (Quite the reverse in some cases, in fact.)
  • leppie
    leppie over 15 years
    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).
  • Jon Skeet
    Jon Skeet over 15 years
    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?
  • endian
    endian over 15 years
    String concatenation is actually fastest up until about 7 strings or so.
  • Echostorm
    Echostorm over 15 years
    Some people will tell you up to 5 strings before stringbuilder. Good post either way.
  • aakpro
    aakpro over 15 years
    +1. Absolutely correct in emphasising how pointless blanket optimisation recommendations are, and how you ABSOLUTELY MUST PROFILE!
  • StingyJack
    StingyJack over 15 years
    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.
  • Boris Callens
    Boris Callens over 15 years
    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?
  • Boris Callens
    Boris Callens over 15 years
    Also nice to see a bit more sane StringBuilder recommendation. More often then not the stringbuilder is wrongly recommended for all situations.
  • Robert S.
    Robert S. over 15 years
    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.
  • Ray Booysen
    Ray Booysen over 15 years
    Or even better, More Effective C#
  • Jack Marchetti
    Jack Marchetti almost 15 years
    I think just using StringBuilder gets you into the habit of always using it.