C# Best Practices and Performance Tuning
collection.ForEach(a => {
//ToDo
})
//Works well with Big Data Set
Parallel.ForEach(collection, k => {
//ToDo
})
//Works well with Big Data set
collection.AsParallel().ForAll(k => {
//ToDo
})
//Somewhat efficient way to loop through a list
public void Loop(){
foreach(var i in CollectionMarshal.AsSpan(myCollection)){
//Do Something
}
}
//Prefered way by using for loop since for loop is faster than for each loop
//really fast, no memory allocation
//This is only safe if you are not changing items in the list you are working with
public void LoopBest(){
var spane = CollectionsMarshal.AsSpan(myCollection);
for(var i = 0; i < span.Lengthe; i++){
var item = span[i];
}
}
- *3 Source: YouTube.com by Nick Chapsis (Fastest way to iterate a List in C-Sharp)
3. In Asp.Net Core 7, you can now loop through the Data coming from the Database Context using await foreach, see the code below:
//Keep in mind that this will stream the data back to the UI, if the UI is stateless then it won't
//know of any new data, you need to use Websockets or some sort.
await foreach(var user in _context.Users.AsAsyncEnumerable()){
//Do the thingy
}
2. Look in C# Class Destructors, basically, it reverses the Constructor Setters and gets Properties. e.g.
var (h,t, k,c) = myNiceClassConstructor();
3. How to Deallocate Objects in a Class after Use
- Use Structs (Value-based references "me" and "Me" are not equal)
- Use Spans
- Use Array Pooling
- Never Load Data in memory you don't need, (The CPU fetches data it does not need from memory and then dumps it, garbage)
If the CPU has a small Cache-Line, it is forced to go roundtrip to Memory to get the Data (that it does not even need).
4. CPU Operations
- Prefetcher fetches data from Memory and Populates
5. Shorter tables Columns are faster than longer Table Columns this is because a Developer can restrict how many rows to retrieve by using a where clause.
6. Performance "How to deallocate Objects in Memory" or at least free memory up after usage
- Make use of IDisposabled and dispose of objects in that class after usage
- (My Own theory): Call GC to clean up regularly so objects allocated on the Stack can be collected and free up memory.
- Use a "Using Statement" to implement IO operations, this frees up objects allocated on the Stack as well as the Heap after usage.
- Use WeakReferences<MyClassObject> to work with Data Modals, this lets the GC know to collect that Object Allocation in memory after it has been used.
e.g. Dictionary<int, WeakReference<MyDataModalClass>> _myDictionary = new();
- [NB] You can allocate Memory in C# by using: private intPtr _head = Marshale.AllocGlobal(4);
Tools to help Look into Memory Usage of an Application
- Use DotPeek (app developed by JetBrain) to peak into Memory Usage
- Use Windows Built-In "Performance Monitor" to monitor Gen1, Gen2, and Gen3 Object Allocation in Memory
Deploying to Production
1. Disable Logging when possible
- When things are going well without Errors, disable Logging to the Console as this has a major impact on the Performance of an Application.
- Respect the Hot Path, make sure you get the User Out of the Server as soon as possible and let other processing of the User Event follow up on a
different Compute Server. This will save you money and time.
References and Resources to follow
- Here is a related Article https://ernestech.com/articles/details/3871
- If you are passionate about the Speed of your code, it is important that you consider, Cache/Memory
hierarchy as you design and implement your algorithms and data structure
- Jan Gray
- Cache-Line is Key!! undoubtedly if you will make even a single error in data layout, you will get 100 x slower solutions! No Joke.
- Dimtriy Vyukov
Jack said:
Hi