11

When I was reading this tutorial I noticed the following performance tip about using structs in C#:

Unless you need reference type semantics, a class that is smaller than 16 bytes may be more efficiently handled by the system as a struct.

I looked for similar question in stackoverflow and I found some questions that talk about performance best practices in ADO.Net, Networking, Streams, but not about performance best practices in C# (The language).

I want to add another tip about using the integer types:

The runtime optimizes the performance of 32-bit integer types (Int32 and UInt32), so use those types for counters and other frequently accessed integral variables.

Community
  • 1
  • 1
Homam
  • 23,263
  • 32
  • 111
  • 187

10 Answers10

14

Simply: profile.

Every app is different. Taking time to reduce some code to make it "more efficient" is meaningless if that is not a bottleneck in you app. Also - you may even be making things worse if you don't have numbers to support changes.

In most cases IO is the pinch-point, so thinking about IO is a no-brainer. Ditto DB access. But beyond that: measure it.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
12
  1. Strings are Immutable.
  2. Understand the using statement.
  3. Understand Boxing and how Generics help.
  4. Understand how the Garbage Collector works.
  5. Parallel programming in .Net 4.0
  6. Understand how File IO affects performance.

Eric Lippert talks alot about optimization. I would read his blog.
I would check out Jon Skeet's blog also.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
kemiller2002
  • 113,795
  • 27
  • 197
  • 251
  • 2
    7: Premature optimization is the root of all evil. Make it work first; if it works with a series of string-appending lines, that's great. If that results in a noticeably slow execution time that you want to improve, you can refactor to use a StringBuilder later. – KeithS Oct 18 '10 at 00:00
  • 1
    @KeithS: Premature optimisation is a bad thing, but using StringBuilder isn't good just for speed issues. It also makes clear that you intend to change the string you have created. It is a semantically sound choice for plenty of settings. – Matt Ellen Oct 18 '10 at 07:39
3
HTTP 410
  • 17,300
  • 12
  • 76
  • 127
2

Don't use exceptions in non-exceptional circumstances.

Paul Creasey
  • 28,321
  • 10
  • 54
  • 90
  • Meh. While that's *definitely* good practice, they don't really affect real world performance. I remember a long time ago when I tried to make a game in Java2D, that my way to do concurrency was to just catch the exceptions when two threads tried to read from the same `ArrayList` at the same time. And we're talking about many thousands of exceptions per second. Exceptions *seem* really slow when you have the debugger attached, but without it they don't affect performance unless you have some serious bad design (like exception based parallelism..). – JulianR Oct 18 '10 at 17:09
  • 1
    Not in the same way as IO can, but in the same order of magnitude as failing to understand strings are immutable! – Paul Creasey Oct 18 '10 at 22:54
  • 1
    Late: But I want to clarify that exceptions themselves are not bad. It's when the **developer** writes `throw` that the code starts to smell. Creating and Catching exceptions are the same as any other execution. Throwing exceptions performs a Non-Local GoTo that is a no-no for controlling code-flow and also hurts performance, as Paul says, in the same order of magnitude as failing to understand strings are immutable. My point being to specify it's the `Throw` that hurts. Not the catch. – Suamere Jan 04 '16 at 16:00
1

Not just in C#, but in any OO language where you are encouraged to make lots of data structure classes, it will probably take some performance tuning and profiling experience to learn this, but keep it simple is more than just a plattitude.

It is essential to minimize the number of classes you have, minimize the redundancy of the data, and especially minimize the use of notification-style updating to try to keep the data consistent.

If different components of the data structure need to be kept consistent with each other, it is better to be able to tolerate temporary inconsistency than to try, through notifications, to keep things tightly in agreement.

Many of the complications that are put into data structure arise out of a vague but pervasive desire to make it "more efficient", such as cross-linking data structures so that notifications can implement instantaneous updates. Not only does that greatly complicate the code, leading to bugs, but then when you do performance tuning you find out it is those structures that can be the biggest performance-killers.

Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135
0

Avoid boxing and unboxing in loops.

For example instead of ArrayList use List. Generic collections are not only type-safe but are also faster than non-generics when you use them with value-types.

Carlos Muñoz
  • 17,397
  • 7
  • 55
  • 80
0

I can name a lot of performance optimisations :

  1. String.Format / StringBuilder for string manipulation as string is immutable.
  2. Inherit IDisposable to write your own code for disposal of objects, so that you remove unmanaged memory references, and also do not implement IDisposable when you are only working with managed memory.
  3. Do not set local references to null, as it is done automatically.
  4. Do not create a new exception while you are throw. Use throw than throw ex
  5. Put large objects as WeakReference, which makes it available to GC immediately. http://www.abhisheksur.com/2010/07/garbage-collection-algorithm-with-use.html
  6. Avoid Boxing / Unboxing. Use Generics.

etc.

abhishek
  • 2,975
  • 23
  • 38
  • 3
    -1 Some of your suggestions are on the right track, but without more context they can be misleading, especially points 3 and 5. "Do not set local references to null" is vague and can be misleading. I think I know what you mean, but it would need a lot more explanation. WeakReferences are only appropriate in rare cases, not for any objects that are large. – EMP Oct 17 '10 at 23:00
  • Yes. I just put the points. Little more explanation would be worth. Thanks for pointing it out. – abhishek Oct 18 '10 at 20:59
  • -1. First, you mean **implement** IDisposable, not inherit. Second, I'd more readily tell a developer to never implement IDisposable than to use it for code he feels needs to be disposed. A general C# developer should understand that every class in the .NET Framework is managed. And if it handles unmanaged resources, it already implements IDisposable. Only Sr. or Architects should be working on the service boundaries where manual handling of unmanaged resources takes place. Implementing IDisposable incorrectly is a huge performance hit, and it is incorrect most of the time. Stinky code smell. – Suamere Jan 04 '16 at 16:23
  • Also, you are correct to mention exception handling as a sore-point for performance. But the sore point is the throw and throw ex. Throwing is the bad part of exception handling. Creating new exceptions is not bad at all. On that same note: You shouldn't catch an exception you can't handle, so throw and throw ex should almost never be seen. If you require to partially handle it then catch, handle it, and return a monad which describes to the consumer what the status of the operation was. Or, at worst case, throw a custom exception that describes the same. – Suamere Jan 04 '16 at 16:29
0

In many apps, especially web apps, your app spends most of its time hitting a database. (This is not C# specific) Use a profiling tool to ensure that you do not have long running db queries, select good indexes, and use eager-loading where appropriate to cut down the number of database requests you have to make. This is probably the single biggest thing you can do to improve performance of an app that uses a database, C# or otherwise.

Doug R
  • 5,749
  • 2
  • 28
  • 32
0

If you subscribe to an event on object "A" from object "B", be sure to unsubscribe from "B"'s events in "A" before "B" changes, otherwise, "B" may never get GC'd.

Hugo
  • 1,814
  • 1
  • 15
  • 23
0

Avoid string operations where possible (lookups, .Contains("blah"), etc.) when doing massive amounts of operations. I have found significant performance enhancements when removing operations like these where possible.

mike
  • 3,146
  • 5
  • 32
  • 46