DEV Community

Cover image for 5 (Extreme) Performance Tips in C# đŸ”„

5 (Extreme) Performance Tips in C# đŸ”„

ByteHide on September 09, 2021

This article is transcribed from Bartosz Adamczewski’s video on LevelUp’s Youtube channel about 5 (Extreme) Performance Tips in C#. This transcrip...
Collapse
 
badamczewski01 profile image
Info Comment hidden by post author - thread only accessible via permalink
Bartosz Adamczewski

This article is copied wholesale from my youtube video: youtube.com/watch?v=Tb2Fx9qku_o

If you're going to copy all of the things 1to1, then at least you should credit the author.

Collapse
 
kenrogoway profile image
Ken Rogoway

Overall a good article, but the example code has a lot of bugs. So it is hard to know if what is shown was used for your performance tests. If it was then your speed improvements may have more to do with optimizations for invariants. For instance in #3 you add to “counter”, but return the sum of counterA and counterB which are both zero. Similar issue in #4, and it also uses the wrong value for the B portion (you’re using p[0] for both A and B sums.

Collapse
 
denisvlah profile image
Denis Vlah

Found how to eliminate multiplication. It makes the code just a little bit faster compared to SumOdd_BranchFree but this technique performs worse than multiplication methods with parallel execution.
The code is the following:

private static int SumOdd_BranchFree_NoMultiply(int[] array)
        {
            int mask = -1; // in binary format is 11111111111111111111111111111111
            int counter = 0;
            for (int i = 0; i < array.Length; i++)
            {
                var element = array[i];
                var odd = element & 1;
                var elementMask = ~(mask + odd); // will cause int overflow if odd == 1 
                counter += (element & elementMask);
            }
            return counter;
        }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
cantak profile image
cantak • Edited

Here's one more option to consider. It's twice as fast as the best one above and uses the bitwise step in actual parallel processing. It probably could have further optimizations from above incorporated into it also. With this you'd call ParallelLoop(array, numberOfTasksYouWantForYourMachine).

Also, I had never thought of bit checking before and have always used mod. I will certainly use this in the future. Nice article!

private static long AddViaGap(long[] array, int gap, int offset) {
long counter = 0;
for (int i = offset; i < array.Length; i += gap) {
var element = array[i];
var odd = element & 1;
counter += (odd * element);
}
return counter;
}

private static long ParallelLoop(long[] array, int taskCount) {
var tasks = new Task[taskCount];
for (var counter = 0; counter < taskCount; counter++) {
var currentCounter = counter;
tasks[counter] = Task.Run(() => AddViaGap(array, taskCount, currentCounter));
}
Task.WaitAll(tasks);
return tasks.Sum(o => o.Result);
}

Collapse
 
rosskillen profile image
rosskillen

Good tips, thanks. Not strong on C# myself but surely you've introduced a bug at stage 3, e.g. if your array has an odd length? I.e. elementB won't exist.

Collapse
 
semidewi profile image
Semidewi

You could get rid of the multiplication by defining a array with length 2.

First entry at Index 0 is 0
Second entry at index 1 is -1

Instead of multiplying value by 1 or 0, you could simply do a Bitwise AND Operation with the value at Index 1 or 0.

Collapse
 
dariojavierrick profile image
Dario Javier Rick

great article! thanks for sharing!

Collapse
 
bytehide profile image
ByteHide

🔒🔒🔒🔒🔒

Collapse
 
marylynch profile image
Maryanne

Nice article.

Collapse
 
bytehide profile image
ByteHide

☕☕☕☕☕

Collapse
 
leonardas profile image
Leonardas

Link to the original video
youtu.be/Tb2Fx9qku_o

Some comments have been hidden by the post's author - find out more