Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Performance penalty of Debug.Assert in .NET

Performance penalty of Debug.Assert in .NET

Scheduled Pinned Locked Moved C#
csharpquestionc++visual-studiodebugging
11 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Rob Philpott

    I'm writing some low level C# which is doing bit level operations (shifting/logic) which needs to be very high performance (real time application). Usually, I'd just do some checks and throw an exception if things aren't right, but I can't afford the overhead of that here. Back in the day, in C++ I'd just use assertions for my checks which would cease to exist completely in the release build. In C#, we have Debug.Assert but its use seems greyer to me, because debug vs. release in .NET is greyer. Macros disappear depending on switches, but it seems the only way a Debug.Assert can disappear is if its hardedcoded in the JIT that way. So my question I guess is does the Debug.Assert make it into the MSIL regardless of debug/release, and then does the JIT just remove it for release and remove it completely? What happens with something like this in a release build, does the counter increment?

    Debug.Assert(++counter != 100);

    Regards, Rob Philpott.

    OriginalGriffO Offline
    OriginalGriffO Offline
    OriginalGriff
    wrote on last edited by
    #2

    See here: Assertions in Managed Code - Visual Studio | Microsoft Docs[^]

    Quote:

    In Visual Basic and Visual C#, you can use the Assert method from either Debug or Trace, which are in the System.Diagnostics namespace. Debug class methods are not included in a Release version of your program, so they do not increase the size or reduce the speed of your release code.

    I'd be tempted to check with ILSpy, but I believe all the assertion code including the condition check are discarded in Release builds.

    "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony AntiTwitter: @DalekDave is now a follower!

    "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
    "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

    1 Reply Last reply
    0
    • R Rob Philpott

      I'm writing some low level C# which is doing bit level operations (shifting/logic) which needs to be very high performance (real time application). Usually, I'd just do some checks and throw an exception if things aren't right, but I can't afford the overhead of that here. Back in the day, in C++ I'd just use assertions for my checks which would cease to exist completely in the release build. In C#, we have Debug.Assert but its use seems greyer to me, because debug vs. release in .NET is greyer. Macros disappear depending on switches, but it seems the only way a Debug.Assert can disappear is if its hardedcoded in the JIT that way. So my question I guess is does the Debug.Assert make it into the MSIL regardless of debug/release, and then does the JIT just remove it for release and remove it completely? What happens with something like this in a release build, does the counter increment?

      Debug.Assert(++counter != 100);

      Regards, Rob Philpott.

      OriginalGriffO Offline
      OriginalGriffO Offline
      OriginalGriff
      wrote on last edited by
      #3

      I just checked, and Debug.Assert is completely removed from Release code: Code:

          private void FrmMain\_Shown(object sender, EventArgs e)
              {
              ...
              string\[\] dataWithCounts = dataFromTextBox.GroupBy(d => d).Select(g =>$"{g.Key}({g.Count()})").ToArray();
              Debug.Assert(dataWithCounts.Count() != 3);
              }
      

      Debug:

      IL_008c: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Select, string>(class [mscorlib]System.Collections.Generic.IEnumerable`1, class [mscorlib]System.Func`2)
      IL_0091: call !!0[] [System.Core]System.Linq.Enumerable::ToArray(class [mscorlib]System.Collections.Generic.IEnumerable`1)
      IL_0096: stloc.1
      IL_0097: ldloc.1
      IL_0098: call int32 [System.Core]System.Linq.Enumerable::Count(class [mscorlib]System.Collections.Generic.IEnumerable`1)
      IL_009d: ldc.i4.3
      IL_009e: ceq
      IL_00a0: ldc.i4.0
      IL_00a1: ceq
      IL_00a3: call void [System]System.Diagnostics.Debug::Assert(bool)
      IL_00a8: nop
      IL_00a9: ret
      } // end of method FrmMain::FrmMain_Shown

      Release:

      IL\_0089: call class \[mscorlib\]System.Collections.Generic.IEnumerable\`1 \[System.Core\]System.Linq.Enumerable::Select, string>(class \[mscorlib\]System.Collections.Generic.IEnumerable\`1, class \[mscorlib\]System.Func\`2)
      IL\_008e: call !!0\[\] \[System.Core\]System.Linq.Enumerable::ToArray(class \[mscorlib\]System.Collections.Generic.IEnumerable\`1)
      IL\_0093: pop
      IL\_0094: ret
      

      "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony AntiTwitter: @DalekDave is now a follower!

      "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
      "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

      R 2 Replies Last reply
      0
      • OriginalGriffO OriginalGriff

        I just checked, and Debug.Assert is completely removed from Release code: Code:

            private void FrmMain\_Shown(object sender, EventArgs e)
                {
                ...
                string\[\] dataWithCounts = dataFromTextBox.GroupBy(d => d).Select(g =>$"{g.Key}({g.Count()})").ToArray();
                Debug.Assert(dataWithCounts.Count() != 3);
                }
        

        Debug:

        IL_008c: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Select, string>(class [mscorlib]System.Collections.Generic.IEnumerable`1, class [mscorlib]System.Func`2)
        IL_0091: call !!0[] [System.Core]System.Linq.Enumerable::ToArray(class [mscorlib]System.Collections.Generic.IEnumerable`1)
        IL_0096: stloc.1
        IL_0097: ldloc.1
        IL_0098: call int32 [System.Core]System.Linq.Enumerable::Count(class [mscorlib]System.Collections.Generic.IEnumerable`1)
        IL_009d: ldc.i4.3
        IL_009e: ceq
        IL_00a0: ldc.i4.0
        IL_00a1: ceq
        IL_00a3: call void [System]System.Diagnostics.Debug::Assert(bool)
        IL_00a8: nop
        IL_00a9: ret
        } // end of method FrmMain::FrmMain_Shown

        Release:

        IL\_0089: call class \[mscorlib\]System.Collections.Generic.IEnumerable\`1 \[System.Core\]System.Linq.Enumerable::Select, string>(class \[mscorlib\]System.Collections.Generic.IEnumerable\`1, class \[mscorlib\]System.Func\`2)
        IL\_008e: call !!0\[\] \[System.Core\]System.Linq.Enumerable::ToArray(class \[mscorlib\]System.Collections.Generic.IEnumerable\`1)
        IL\_0093: pop
        IL\_0094: ret
        

        "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony AntiTwitter: @DalekDave is now a follower!

        R Offline
        R Offline
        Rob Philpott
        wrote on last edited by
        #4

        That's interesting. I just tried a similar thing with dotPeek, and the assertion is still visible in the release code, though your explanation above seems more plausible. Thanks for the link also - it backs up what you have above. I'm wondering if there is some other optimization switch in play here which explains why I can still see it...

        Regards, Rob Philpott.

        Richard DeemingR 1 Reply Last reply
        0
        • OriginalGriffO OriginalGriff

          I just checked, and Debug.Assert is completely removed from Release code: Code:

              private void FrmMain\_Shown(object sender, EventArgs e)
                  {
                  ...
                  string\[\] dataWithCounts = dataFromTextBox.GroupBy(d => d).Select(g =>$"{g.Key}({g.Count()})").ToArray();
                  Debug.Assert(dataWithCounts.Count() != 3);
                  }
          

          Debug:

          IL_008c: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Select, string>(class [mscorlib]System.Collections.Generic.IEnumerable`1, class [mscorlib]System.Func`2)
          IL_0091: call !!0[] [System.Core]System.Linq.Enumerable::ToArray(class [mscorlib]System.Collections.Generic.IEnumerable`1)
          IL_0096: stloc.1
          IL_0097: ldloc.1
          IL_0098: call int32 [System.Core]System.Linq.Enumerable::Count(class [mscorlib]System.Collections.Generic.IEnumerable`1)
          IL_009d: ldc.i4.3
          IL_009e: ceq
          IL_00a0: ldc.i4.0
          IL_00a1: ceq
          IL_00a3: call void [System]System.Diagnostics.Debug::Assert(bool)
          IL_00a8: nop
          IL_00a9: ret
          } // end of method FrmMain::FrmMain_Shown

          Release:

          IL\_0089: call class \[mscorlib\]System.Collections.Generic.IEnumerable\`1 \[System.Core\]System.Linq.Enumerable::Select, string>(class \[mscorlib\]System.Collections.Generic.IEnumerable\`1, class \[mscorlib\]System.Func\`2)
          IL\_008e: call !!0\[\] \[System.Core\]System.Linq.Enumerable::ToArray(class \[mscorlib\]System.Collections.Generic.IEnumerable\`1)
          IL\_0093: pop
          IL\_0094: ret
          

          "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony AntiTwitter: @DalekDave is now a follower!

          R Offline
          R Offline
          Rob Philpott
          wrote on last edited by
          #5

          Ok explained. dotPeek will use the actual source when its available rather than disassemble. Indeed the assertion never makes into MSIL. I'm learning all sorts of new things today. :)

          Regards, Rob Philpott.

          OriginalGriffO 1 Reply Last reply
          0
          • R Rob Philpott

            That's interesting. I just tried a similar thing with dotPeek, and the assertion is still visible in the release code, though your explanation above seems more plausible. Thanks for the link also - it backs up what you have above. I'm wondering if there is some other optimization switch in play here which explains why I can still see it...

            Regards, Rob Philpott.

            Richard DeemingR Offline
            Richard DeemingR Offline
            Richard Deeming
            wrote on last edited by
            #6

            Does your release build still have the DEBUG conditional compilation symbol defined? Reference Source[^] ConditionalAttribute Class (System.Diagnostics) | Microsoft Docs[^]


            "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

            "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

            R 1 Reply Last reply
            0
            • Richard DeemingR Richard Deeming

              Does your release build still have the DEBUG conditional compilation symbol defined? Reference Source[^] ConditionalAttribute Class (System.Diagnostics) | Microsoft Docs[^]


              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

              R Offline
              R Offline
              Rob Philpott
              wrote on last edited by
              #7

              Nope, good thought though. TRACE is defined. Explanation is below, dotPeek uses the actual source rather than reconstituted when available, so it was showing even for the release build.

              Regards, Rob Philpott.

              1 Reply Last reply
              0
              • R Rob Philpott

                Ok explained. dotPeek will use the actual source when its available rather than disassemble. Indeed the assertion never makes into MSIL. I'm learning all sorts of new things today. :)

                Regards, Rob Philpott.

                OriginalGriffO Offline
                OriginalGriffO Offline
                OriginalGriff
                wrote on last edited by
                #8

                Yeah, I like dotPeek, but that "use the source" bit has thrown me a couple of times. ILSpy is a bit more basic, but sometimes that's exactly what you want.

                "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony AntiTwitter: @DalekDave is now a follower!

                "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
                "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

                L 1 Reply Last reply
                0
                • OriginalGriffO OriginalGriff

                  Yeah, I like dotPeek, but that "use the source" bit has thrown me a couple of times. ILSpy is a bit more basic, but sometimes that's exactly what you want.

                  "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony AntiTwitter: @DalekDave is now a follower!

                  L Offline
                  L Offline
                  Luc Pattyn
                  wrote on last edited by
                  #9

                  Quote:

                  a bit more basic, but sometimes that's exactly what you want.

                  We have a special forum for that :doh:

                  Luc Pattyn [My Articles] Nil Volentibus Arduum

                  OriginalGriffO 1 Reply Last reply
                  0
                  • L Luc Pattyn

                    Quote:

                    a bit more basic, but sometimes that's exactly what you want.

                    We have a special forum for that :doh:

                    Luc Pattyn [My Articles] Nil Volentibus Arduum

                    OriginalGriffO Offline
                    OriginalGriffO Offline
                    OriginalGriff
                    wrote on last edited by
                    #10

                    :laugh: Nobody really wants VB!

                    "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony AntiTwitter: @DalekDave is now a follower!

                    "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
                    "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

                    1 Reply Last reply
                    0
                    • R Rob Philpott

                      I'm writing some low level C# which is doing bit level operations (shifting/logic) which needs to be very high performance (real time application). Usually, I'd just do some checks and throw an exception if things aren't right, but I can't afford the overhead of that here. Back in the day, in C++ I'd just use assertions for my checks which would cease to exist completely in the release build. In C#, we have Debug.Assert but its use seems greyer to me, because debug vs. release in .NET is greyer. Macros disappear depending on switches, but it seems the only way a Debug.Assert can disappear is if its hardedcoded in the JIT that way. So my question I guess is does the Debug.Assert make it into the MSIL regardless of debug/release, and then does the JIT just remove it for release and remove it completely? What happens with something like this in a release build, does the counter increment?

                      Debug.Assert(++counter != 100);

                      Regards, Rob Philpott.

                      J Offline
                      J Offline
                      jsc42
                      wrote on last edited by
                      #11

                      An Assert should never modify data

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups