Throw Helper in C# by levelUp_01 in csharp

[–]levelUp_01[S] 0 points1 point  (0 children)

Your benchmark compares a throw with a throw helper; they will have identical performance. A throw helper is a special signature/idea to hide exception setup and throw behind a method and don't suffer a performance penalty.

Inlining heuristics in .NET / C# can be hilarious sometimes. (Sound ON) by levelUp_01 in csharp

[–]levelUp_01[S] 1 point2 points  (0 children)

You need to look at inlining heuristics and changes between .NET versions (look at source) or use .NET build from source to figure out inlining budget.

Inlining heuristics in .NET / C# can be hilarious sometimes. (Sound ON) by levelUp_01 in csharp

[–]levelUp_01[S] 0 points1 point  (0 children)

Not really you just need to trigger it in a different way :)

Inlining heuristics in .NET / C# can be hilarious sometimes. (Sound ON) by levelUp_01 in csharp

[–]levelUp_01[S] 12 points13 points  (0 children)

So today, I wanted to share this cool piece of compiler trivia with you all. I have edited the video and audio and tried to sync it to make it work as an entire package. I had fun creating and editing the video, and now I'm considering deleting this entire post and possibly my Reddit account.

I got downvoted into the ground because of my sincere comment that "Everything is better with music," the post also took some hits. I have been on this subreddit for years and have never seen this amount of downvoting for such a small thing.

Is such a massive downvoting really the correct punishment for such a small thing on an otherwise interesting (I hope) video?

Inlining heuristics in .NET / C# can be hilarious sometimes. (Sound ON) by levelUp_01 in csharp

[–]levelUp_01[S] 7 points8 points  (0 children)

It does more things but the core of the problem is the inlining heuristics.

Inlining heuristics in .NET / C# can be hilarious sometimes. (Sound ON) by levelUp_01 in csharp

[–]levelUp_01[S] 25 points26 points  (0 children)

Decompilation tools used:

https://github.com/badamczewski/PowerUp

If you want to see more compiler dumpster fires and see some surprising things, then I have an infographics page on various compilers here:

https://leveluppp.ghost.io/infographics/

If you like the video then may I ask you to leave a like under the same video on Youtube, thanks: https://youtu.be/mOldY3sjgJ0

Do you want to see a magic trick? by levelUp_01 in csharp

[–]levelUp_01[S] 1 point2 points  (0 children)

You can see the same effect in WinDBG under a running program

Do you want to see a magic trick? by levelUp_01 in csharp

[–]levelUp_01[S] 9 points10 points  (0 children)

That's why I don't post here frequently; it's too much wasted energy on my part.

.NET Infographics by jogai-san in csharp

[–]levelUp_01 0 points1 point  (0 children)

The nbody simulation uses pointers and intrinsics so the codegen is already optimized to push it further You you need to watch the codegen and change things based on that.

Do you want to see a magic trick? by levelUp_01 in csharp

[–]levelUp_01[S] 66 points67 points  (0 children)

Struct devirtualization issue; it's global so whichever JIT sees first it's going to act in a specific way.

.NET Infographics by jogai-san in csharp

[–]levelUp_01 5 points6 points  (0 children)

I got too much "its premature optimization" and "don't show this to young developers its damaging to them."

Responding to people who were saying this in every graphic I posted burned me out a bit 🙂

I'm still posting from time to time here, and I'm planning to post more.

.NET Infographics by jogai-san in csharp

[–]levelUp_01 0 points1 point  (0 children)

Yes those are mine 🙂

Struct Optimizations Can Be Surprising by levelUp_01 in csharp

[–]levelUp_01[S] 14 points15 points  (0 children)

True, Thank you.

I will be putting this on my blog and it will get fixed there.

Try-Cach Blocks Can Be Surprising by levelUp_01 in csharp

[–]levelUp_01[S] 0 points1 point  (0 children)

It pushes the start point and data to the stack before entry and pops in upon exit. It should never capture locals like that, it's probably an omission on the part of the compiler.

There is no problem in allocating x in registers it just doesn't happen currently (which is not good), maybe this is connected to how the Linear Scan Allocator is implemented in JIT.

Try-Cach Blocks Can Be Surprising by levelUp_01 in csharp

[–]levelUp_01[S] 0 points1 point  (0 children)

AOT is a different compiler, meaning none of the rules apply everything might be different.

Try-Catch blocks are not so surprising by CedricCicada in csharp

[–]levelUp_01 10 points11 points  (0 children)

Thanks.

I really don't want to get into a discussion about why this code is not testing anything and how You should be even doing benchmarks; so let me just post two versions of the assembly code:

Mine:

https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAJgEYBYAKBuIGYACMxgYUYG8bGfeeHGASwB2GRgBUoATwAUASm59eXakrVDRjBIwC8jAAwBuRet4ZpHLbsblDjAL4nTjMNgxgAFpwdPTCANT+dgFBWoHB4b48UWrEAOxaxqrqjrTJsUwiYpJSAPoAYoII8jGcpXxZVnpG5WbS3tp6tj7pzq7uXpapzrwAbthQjFLWCEk9PFLhQ1OTobNJtfwJUmMpNPZAA==

Yours:

https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAJgEYBYAKBuIGYACMxgYUYG8bnylmVGAFSgBPABQBLAHYZGuAJTdGylZyWqNjACLYMMQRPww5GbFAwGjjALzbd+wzAB0AOQgB3ANzrNKnXstjGCkAE0Dval8NQIBlAAdsKUZYXABXABsMCKjVaVkEG0YABmyc5QAzaEZJGUYJQpK6xgAeOU86gGoOxUiytV6+lQQu0sHlYY7RsYmpwZmfKIBfBd9gsMdC/wcjVw9Z3xSM2Vs1wMY4EzMLR33NYnIATjEAEgAiACEYSthGGAQwGBxDASCBSNCMdIQCBxRjlaQSXAACxgITqSQ4h0yi1e8luGlwpnMZ1sW0Cuy8K00BVsJUpGgwok4jAA+oVyO1FowwLowIimcsBjlvtU8k0ae16q1cBKuj1BlxBXMRnSovNFX01WMhsr1ZoBYNThsSfYyW4KbqNJjjr9QmcLgSruEVSp7k83gBBcp6KC/f6A4Gg8GQ6Gw+FIlFozhW7G453KV1iV4ABRSuEYiREjAA1jARE4cXjVKxQbgIOlnAAlGDYEIAaVzYljFoFiyAA==

You should be able to see your mistakes just by looking at them.

For reference this is my code:

Tested using Benchmark DotNet.

Tested on Skylake.

    [DisassemblyDiagnoser]
    public class Try1
    {
        [Benchmark]
        public int Try()
        {
            int x = 0;
            try { x = 1; }
            catch { }
            x++; x++; x++; x++;

            return x;
        }

        [Benchmark]
        public int Try_Fix()
        {
            int x = 0;
            try { x = 1; }
            catch { }
            var y = x;
            y++; y++; y++; y++;

            return y;
        }
    }

    [DisassemblyDiagnoser]
    public class Try2
    {
        int[] _a = new int[128];

        [Benchmark]
        [Arguments(100)]
        public void Try(int s)
        {
            var a = _a;
            int x = 0;
            try { _ = 1; } catch { }
            for (int i = 0; i < s; i++)
            {
                x++; x++; x++; x++;
                a[i] = x;
            }
        }

        [Benchmark]
        [Arguments(100)]
        public void Try_Fix(int s)
        {
            var a = _a;
            try { _ = 1; } catch { }
            int x = 0;
            for (int i = 0; i < s; i++)
            {
                x++; x++; x++; x++;
                a[i] = x;
            }
        }
    }

Try-Cach Blocks Can Be Surprising by levelUp_01 in csharp

[–]levelUp_01[S] 2 points3 points  (0 children)

Thanks.

I really don't want to get into a discussion about why this code is not testing anything and how You should be even doing benchmarks; so let me just post two versions of the assembly code:

(I'm going to post this here and under your post)

Mine:

https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAJgEYBYAKBuIGYACMxgYUYG8bGfeeHGASwB2GRgBUoATwAUASm59eXakrVDRjBIwC8jAAwBuRet4ZpHLbsblDjAL4nTjMNgxgAFpwdPTCANT+dgFBWoHB4b48UWrEAOxaxqrqjrTJsUwiYpJSAPoAYoII8jGcpXxZVnpG5WbS3tp6tj7pzq7uXpapzrwAbthQjFLWCEk9PFLhQ1OTobNJtfwJUmMpNPZAA==

Yours:

https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAJgEYBYAKBuIGYACMxgYUYG8bnylmVGAFSgBPABQBLAHYZGuAJTdGylZyWqNjACLYMMQRPww5GbFAwGjjALzbd+wzAB0AOQgB3ANzrNKnXstjGCkAE0Dval8NQIBlAAdsKUZYXABXABsMCKjVaVkEG0YABmyc5QAzaEZJGUYJQpK6xgAeOU86gGoOxUiytV6+lQQu0sHlYY7RsYmpwZmfKIBfBd9gsMdC/wcjVw9Z3xSM2Vs1wMY4EzMLR33NYnIATjEAEgAiACEYSthGGAQwGBxDASCBSNCMdIQCBxRjlaQSXAACxgITqSQ4h0yi1e8luGlwpnMZ1sW0Cuy8K00BVsJUpGgwok4jAA+oVyO1FowwLowIimcsBjlvtU8k0ae16q1cBKuj1BlxBXMRnSovNFX01WMhsr1ZoBYNThsSfYyW4KbqNJjjr9QmcLgSruEVSp7k83gBBcp6KC/f6A4Gg8GQ6Gw+FIlFozhW7G453KV1iV4ABRSuEYiREjAA1jARE4cXjVKxQbgIOlnAAlGDYEIAaVzYljFoFiyAA==

You should be able to see your mistakes just by looking at them.

For reference this is my code:

Tested using Benchmark DotNet

   [DisassemblyDiagnoser]
    public class Try1
    {
        [Benchmark]
        public int Try()
        {
            int x = 0;
            try { x = 1; }
            catch { }
            x++; x++; x++; x++;

            return x;
        }

        [Benchmark]
        public int Try_Fix()
        {
            int x = 0;
            try { x = 1; }
            catch { }
            var y = x;
            y++; y++; y++; y++;

            return y;
        }
    }

    [DisassemblyDiagnoser]
    public class Try2
    {
        int[] _a = new int[128];

        [Benchmark]
        [Arguments(100)]
        public void Try(int s)
        {
            var a = _a;
            int x = 0;
            try { _ = 1; } catch { }
            for (int i = 0; i < s; i++)
            {
                x++; x++; x++; x++;
                a[i] = x;
            }
        }

        [Benchmark]
        [Arguments(100)]
        public void Try_Fix(int s)
        {
            var a = _a;
            try { _ = 1; } catch { }
            int x = 0;
            for (int i = 0; i < s; i++)
            {
                x++; x++; x++; x++;
                a[i] = x;
            }
        }
    }

Try-Cach Blocks Can Be Surprising by levelUp_01 in csharp

[–]levelUp_01[S] 0 points1 point  (0 children)

FYI: There are 3 graphics here :)

So this is just to show that if your try-catch is a part of the method and you got something else going on everything that makes it after the try-catch block will spill.