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. C# Performance

C# Performance

Scheduled Pinned Locked Moved C#
performancequestioncsharpcss
14 Posts 10 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.
  • M MrEyes

    Out of sheer curiosity I have a quick question relating to C# performance. I have the two following methods:

    public static string VerboseProgrammingMethod()
    {
    System.Guid g = Guid.NewGuid();
    string s = g.ToString();
    string f = s.Substring(0,4);

    return f;
    }

    public static string OneLineProgrammingMethod()
    {
    return Guid.NewGuid().ToString().Substring(0, 4);
    }

    As you can see both of them will generate exactly the same output as they essentially perform the same functions. The question is is one of them quicker/less memory intensive than the other? I am under the impression that it doesnt make any difference whatsoever, but I would be grateful if somebody could confirm this

    J Offline
    J Offline
    J4amieC
    wrote on last edited by
    #2

    run an app called ildasm from the VSNet command prompt and open your assembly with both methods in. You should see that the generated IL is exactly the same.

    1 Reply Last reply
    0
    • M MrEyes

      Out of sheer curiosity I have a quick question relating to C# performance. I have the two following methods:

      public static string VerboseProgrammingMethod()
      {
      System.Guid g = Guid.NewGuid();
      string s = g.ToString();
      string f = s.Substring(0,4);

      return f;
      }

      public static string OneLineProgrammingMethod()
      {
      return Guid.NewGuid().ToString().Substring(0, 4);
      }

      As you can see both of them will generate exactly the same output as they essentially perform the same functions. The question is is one of them quicker/less memory intensive than the other? I am under the impression that it doesnt make any difference whatsoever, but I would be grateful if somebody could confirm this

      K Offline
      K Offline
      krieg38
      wrote on last edited by
      #3

      The first methods creates two strings(s,f) and it should be more memory consuming.

      M G 2 Replies Last reply
      0
      • K krieg38

        The first methods creates two strings(s,f) and it should be more memory consuming.

        M Offline
        M Offline
        mav northwind
        wrote on last edited by
        #4

        I'm afraid that's not true, since the resulting IL is identical. Regards, mav

        1 Reply Last reply
        0
        • M MrEyes

          Out of sheer curiosity I have a quick question relating to C# performance. I have the two following methods:

          public static string VerboseProgrammingMethod()
          {
          System.Guid g = Guid.NewGuid();
          string s = g.ToString();
          string f = s.Substring(0,4);

          return f;
          }

          public static string OneLineProgrammingMethod()
          {
          return Guid.NewGuid().ToString().Substring(0, 4);
          }

          As you can see both of them will generate exactly the same output as they essentially perform the same functions. The question is is one of them quicker/less memory intensive than the other? I am under the impression that it doesnt make any difference whatsoever, but I would be grateful if somebody could confirm this

          L Offline
          L Offline
          leppie
          wrote on last edited by
          #5

          Like the others say, both are the same. #1 is must easier to debug though, and should allways be used (for clarity too). Make a habit of it. We are proffesionals, not script kiddie/wannabe hackers :) NOTE: That saying, I still take the 'short' route sometimes :-O xacc.ide-0.1.1.4 - now with LSharp integration and scripting :)

          M 1 Reply Last reply
          0
          • L leppie

            Like the others say, both are the same. #1 is must easier to debug though, and should allways be used (for clarity too). Make a habit of it. We are proffesionals, not script kiddie/wannabe hackers :) NOTE: That saying, I still take the 'short' route sometimes :-O xacc.ide-0.1.1.4 - now with LSharp integration and scripting :)

            M Offline
            M Offline
            MrEyes
            wrote on last edited by
            #6

            I totally agree with your professionals vs script kiddie comment, but on occasion it is sometimes necessary to make sacrifices for performance. As suggested by Jamie4C I created the following class library and ran it through ILDasm

            public class Class1
            {
            public static string VerboseProgrammingMethod()
            {
            System.Guid g = Guid.NewGuid();
            string s = g.ToString();
            string f = s.Substring(0,4);

            return f;
            }

            public static string OneLineProgrammingMethod()
            {
            return Guid.NewGuid().ToString().Substring(0, 4);
            }
            }
            }

            Now in theory the IL code for these two functions should be exactly the same, interestingly there are differences. I am no IL expert so this might be a red herring, but here is the IL code:

            .method public hidebysig static string VerboseProgrammingMethod() cil managed
            {
            // Code size 29 (0x1d)
            .maxstack 3
            .locals init ([0] valuetype [mscorlib]System.Guid g,
            [1] string s,
            [2] string f,
            [3] string CS$00000003$00000000)
            IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
            IL_0005: stloc.0
            IL_0006: ldloca.s g
            IL_0008: call instance string [mscorlib]System.Guid::ToString()
            IL_000d: stloc.1
            IL_000e: ldloc.1
            IL_000f: ldc.i4.0
            IL_0010: ldc.i4.4
            IL_0011: callvirt instance string [mscorlib]System.String::Substring(int32,
            int32)
            IL_0016: stloc.2
            IL_0017: ldloc.2
            IL_0018: stloc.3
            IL_0019: br.s IL_001b
            IL_001b: ldloc.3
            IL_001c: ret
            } // end of method Class1::VerboseProgrammingMethod

            .method public hidebysig static string OneLineProgrammingMethod() cil managed
            {
            // Code size 25 (0x19)
            .maxstack 3
            .locals init ([0] string CS$00000003$00000000,
            [1] valuetype [mscorlib]System.Guid CS$00000002$00000001)
            IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
            IL_0005: stloc.1
            IL_0006: ldloca.s CS$00000002$00000001
            IL_0008: call instance string [mscorlib]System.Guid::ToString()
            IL_000d: ldc.i4.0
            IL_000e: ldc.i4.4
            IL_000f: callvirt instance string [mscorlib]System.String::Substring(int32,
            int32)
            IL_0014: stloc.0
            IL_0015: br.s IL_0017
            IL_0017: ldloc.0
            IL_0018: ret
            } // end of method Class1::OneLineProgrammingMethod

            C 1 Reply Last reply
            0
            • M MrEyes

              I totally agree with your professionals vs script kiddie comment, but on occasion it is sometimes necessary to make sacrifices for performance. As suggested by Jamie4C I created the following class library and ran it through ILDasm

              public class Class1
              {
              public static string VerboseProgrammingMethod()
              {
              System.Guid g = Guid.NewGuid();
              string s = g.ToString();
              string f = s.Substring(0,4);

              return f;
              }

              public static string OneLineProgrammingMethod()
              {
              return Guid.NewGuid().ToString().Substring(0, 4);
              }
              }
              }

              Now in theory the IL code for these two functions should be exactly the same, interestingly there are differences. I am no IL expert so this might be a red herring, but here is the IL code:

              .method public hidebysig static string VerboseProgrammingMethod() cil managed
              {
              // Code size 29 (0x1d)
              .maxstack 3
              .locals init ([0] valuetype [mscorlib]System.Guid g,
              [1] string s,
              [2] string f,
              [3] string CS$00000003$00000000)
              IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
              IL_0005: stloc.0
              IL_0006: ldloca.s g
              IL_0008: call instance string [mscorlib]System.Guid::ToString()
              IL_000d: stloc.1
              IL_000e: ldloc.1
              IL_000f: ldc.i4.0
              IL_0010: ldc.i4.4
              IL_0011: callvirt instance string [mscorlib]System.String::Substring(int32,
              int32)
              IL_0016: stloc.2
              IL_0017: ldloc.2
              IL_0018: stloc.3
              IL_0019: br.s IL_001b
              IL_001b: ldloc.3
              IL_001c: ret
              } // end of method Class1::VerboseProgrammingMethod

              .method public hidebysig static string OneLineProgrammingMethod() cil managed
              {
              // Code size 25 (0x19)
              .maxstack 3
              .locals init ([0] string CS$00000003$00000000,
              [1] valuetype [mscorlib]System.Guid CS$00000002$00000001)
              IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
              IL_0005: stloc.1
              IL_0006: ldloca.s CS$00000002$00000001
              IL_0008: call instance string [mscorlib]System.Guid::ToString()
              IL_000d: ldc.i4.0
              IL_000e: ldc.i4.4
              IL_000f: callvirt instance string [mscorlib]System.String::Substring(int32,
              int32)
              IL_0014: stloc.0
              IL_0015: br.s IL_0017
              IL_0017: ldloc.0
              IL_0018: ret
              } // end of method Class1::OneLineProgrammingMethod

              C Offline
              C Offline
              Colin Angus Mackay
              wrote on last edited by
              #7

              Is this the debug or the release build? There shouldn't be any differences in the release build. The debug build will contain some differences which is why the first version of the code is easier to debug (the compiler doesn't perform so many optimisations in debug builds) ColinMackay.net "Man who stand on hill with mouth open will wait long time for roast duck to drop in." -- Confucius "If a man empties his purse into his head, no man can take it away from him, for an investment in knowledge pays the best interest." -- Joseph E. O'Donnell

              M 1 Reply Last reply
              0
              • C Colin Angus Mackay

                Is this the debug or the release build? There shouldn't be any differences in the release build. The debug build will contain some differences which is why the first version of the code is easier to debug (the compiler doesn't perform so many optimisations in debug builds) ColinMackay.net "Man who stand on hill with mouth open will wait long time for roast duck to drop in." -- Confucius "If a man empties his purse into his head, no man can take it away from him, for an investment in knowledge pays the best interest." -- Joseph E. O'Donnell

                M Offline
                M Offline
                MrEyes
                wrote on last edited by
                #8

                The above IL listings were from a debug build, but there are still differences in a release build:

                .method public hidebysig static string VerboseProgrammingMethod() cil managed
                {
                // Code size 25 (0x19)
                .maxstack 3
                .locals init (valuetype [mscorlib]System.Guid V_0,
                string V_1,
                string V_2)
                IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
                IL_0005: stloc.0
                IL_0006: ldloca.s V_0
                IL_0008: call instance string [mscorlib]System.Guid::ToString()
                IL_000d: stloc.1
                IL_000e: ldloc.1
                IL_000f: ldc.i4.0
                IL_0010: ldc.i4.4
                IL_0011: callvirt instance string [mscorlib]System.String::Substring(int32,
                int32)
                IL_0016: stloc.2
                IL_0017: ldloc.2
                IL_0018: ret
                } // end of method Class1::VerboseProgrammingMethod

                .method public hidebysig static string OneLineProgrammingMethod() cil managed
                {
                // Code size 21 (0x15)
                .maxstack 3
                .locals init (valuetype [mscorlib]System.Guid V_0)
                IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
                IL_0005: stloc.0
                IL_0006: ldloca.s V_0
                IL_0008: call instance string [mscorlib]System.Guid::ToString()
                IL_000d: ldc.i4.0
                IL_000e: ldc.i4.4
                IL_000f: callvirt instance string [mscorlib]System.String::Substring(int32,
                int32)
                IL_0014: ret
                } // end of method Class1::OneLineProgrammingMethod

                -- modified at 7:31 Monday 9th January, 2006

                M L 2 Replies Last reply
                0
                • M MrEyes

                  The above IL listings were from a debug build, but there are still differences in a release build:

                  .method public hidebysig static string VerboseProgrammingMethod() cil managed
                  {
                  // Code size 25 (0x19)
                  .maxstack 3
                  .locals init (valuetype [mscorlib]System.Guid V_0,
                  string V_1,
                  string V_2)
                  IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
                  IL_0005: stloc.0
                  IL_0006: ldloca.s V_0
                  IL_0008: call instance string [mscorlib]System.Guid::ToString()
                  IL_000d: stloc.1
                  IL_000e: ldloc.1
                  IL_000f: ldc.i4.0
                  IL_0010: ldc.i4.4
                  IL_0011: callvirt instance string [mscorlib]System.String::Substring(int32,
                  int32)
                  IL_0016: stloc.2
                  IL_0017: ldloc.2
                  IL_0018: ret
                  } // end of method Class1::VerboseProgrammingMethod

                  .method public hidebysig static string OneLineProgrammingMethod() cil managed
                  {
                  // Code size 21 (0x15)
                  .maxstack 3
                  .locals init (valuetype [mscorlib]System.Guid V_0)
                  IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
                  IL_0005: stloc.0
                  IL_0006: ldloca.s V_0
                  IL_0008: call instance string [mscorlib]System.Guid::ToString()
                  IL_000d: ldc.i4.0
                  IL_000e: ldc.i4.4
                  IL_000f: callvirt instance string [mscorlib]System.String::Substring(int32,
                  int32)
                  IL_0014: ret
                  } // end of method Class1::OneLineProgrammingMethod

                  -- modified at 7:31 Monday 9th January, 2006

                  M Offline
                  M Offline
                  Mike Dimmick
                  wrote on last edited by
                  #9

                  After a lot of pain I managed to get the Windows Debugger hooked up to a process containing these two methods (using the MethodImpl attribute to suppress inlining), and dump the JITted code. Here's the result: OneLineProgrammingMethod:

                  sub esp,0x10
                  xor eax,eax
                  mov [esp],eax
                  mov [esp+0x4],eax
                  mov [esp+0x8],eax
                  mov [esp+0xc],eax
                  lea ecx,[esp]
                  call mscorlib_79990000+0x35d28 (799c5d28)

                  push 0x0
                  lea ecx,[esp+0x4]
                  mov edx,[01c415d0]
                  call mscorlib_79990000+0x35de0 (799c5de0)
                  push 0x4
                  mov ecx,eax
                  xor edx,edx
                  cmp [ecx],ecx

                  call mscorlib_79990000+0x6b20 (79996b20)
                  add esp,0x10
                  ret

                  VerboseProgrammingMethod:

                  sub esp,0x10
                  xor eax,eax
                  mov [esp],eax
                  mov [esp+0x4],eax
                  mov [esp+0x8],eax
                  mov [esp+0xc],eax
                  lea ecx,[esp]
                  call dword ptr [mscorlib_79990000+0x234a08 (79bc4a08)]

                  push 0x0
                  lea ecx,[esp+0x4]
                  mov edx,[01c415d0]
                  call dword ptr [mscorlib_79990000+0x234a28 (79bc4a28)]
                  push 0x4
                  mov ecx,eax
                  xor edx,edx
                  cmp [ecx],ecx

                  call mscorlib_79990000+0x6b20 (79996b20)
                  add esp,0x10
                  ret

                  The only difference is that for some reason the JIT compiler has decided to call through a table for the verbose method - the functions called are exactly the same. I'm actually surprised - I was expecting the IL to be different since the C# compiler does very little optimisation but I wasn't expecting a difference in the JITted code. Nevertheless you should normally forget about micro-optimisations like this and concentrate on the areas that will have the biggest impact. Stability. What an interesting concept. -- Chris Maunder

                  M 1 Reply Last reply
                  0
                  • M MrEyes

                    The above IL listings were from a debug build, but there are still differences in a release build:

                    .method public hidebysig static string VerboseProgrammingMethod() cil managed
                    {
                    // Code size 25 (0x19)
                    .maxstack 3
                    .locals init (valuetype [mscorlib]System.Guid V_0,
                    string V_1,
                    string V_2)
                    IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
                    IL_0005: stloc.0
                    IL_0006: ldloca.s V_0
                    IL_0008: call instance string [mscorlib]System.Guid::ToString()
                    IL_000d: stloc.1
                    IL_000e: ldloc.1
                    IL_000f: ldc.i4.0
                    IL_0010: ldc.i4.4
                    IL_0011: callvirt instance string [mscorlib]System.String::Substring(int32,
                    int32)
                    IL_0016: stloc.2
                    IL_0017: ldloc.2
                    IL_0018: ret
                    } // end of method Class1::VerboseProgrammingMethod

                    .method public hidebysig static string OneLineProgrammingMethod() cil managed
                    {
                    // Code size 21 (0x15)
                    .maxstack 3
                    .locals init (valuetype [mscorlib]System.Guid V_0)
                    IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
                    IL_0005: stloc.0
                    IL_0006: ldloca.s V_0
                    IL_0008: call instance string [mscorlib]System.Guid::ToString()
                    IL_000d: ldc.i4.0
                    IL_000e: ldc.i4.4
                    IL_000f: callvirt instance string [mscorlib]System.String::Substring(int32,
                    int32)
                    IL_0014: ret
                    } // end of method Class1::OneLineProgrammingMethod

                    -- modified at 7:31 Monday 9th January, 2006

                    L Offline
                    L Offline
                    Lost User
                    wrote on last edited by
                    #10

                    The latter seems to be faster, is this correct?

                    D 1 Reply Last reply
                    0
                    • M Mike Dimmick

                      After a lot of pain I managed to get the Windows Debugger hooked up to a process containing these two methods (using the MethodImpl attribute to suppress inlining), and dump the JITted code. Here's the result: OneLineProgrammingMethod:

                      sub esp,0x10
                      xor eax,eax
                      mov [esp],eax
                      mov [esp+0x4],eax
                      mov [esp+0x8],eax
                      mov [esp+0xc],eax
                      lea ecx,[esp]
                      call mscorlib_79990000+0x35d28 (799c5d28)

                      push 0x0
                      lea ecx,[esp+0x4]
                      mov edx,[01c415d0]
                      call mscorlib_79990000+0x35de0 (799c5de0)
                      push 0x4
                      mov ecx,eax
                      xor edx,edx
                      cmp [ecx],ecx

                      call mscorlib_79990000+0x6b20 (79996b20)
                      add esp,0x10
                      ret

                      VerboseProgrammingMethod:

                      sub esp,0x10
                      xor eax,eax
                      mov [esp],eax
                      mov [esp+0x4],eax
                      mov [esp+0x8],eax
                      mov [esp+0xc],eax
                      lea ecx,[esp]
                      call dword ptr [mscorlib_79990000+0x234a08 (79bc4a08)]

                      push 0x0
                      lea ecx,[esp+0x4]
                      mov edx,[01c415d0]
                      call dword ptr [mscorlib_79990000+0x234a28 (79bc4a28)]
                      push 0x4
                      mov ecx,eax
                      xor edx,edx
                      cmp [ecx],ecx

                      call mscorlib_79990000+0x6b20 (79996b20)
                      add esp,0x10
                      ret

                      The only difference is that for some reason the JIT compiler has decided to call through a table for the verbose method - the functions called are exactly the same. I'm actually surprised - I was expecting the IL to be different since the C# compiler does very little optimisation but I wasn't expecting a difference in the JITted code. Nevertheless you should normally forget about micro-optimisations like this and concentrate on the areas that will have the biggest impact. Stability. What an interesting concept. -- Chris Maunder

                      M Offline
                      M Offline
                      MrEyes
                      wrote on last edited by
                      #11

                      Mike Dimmick wrote:

                      Nevertheless you should normally forget about micro-optimisations like this and concentrate on the areas that will have the biggest impact.

                      In this example, I agree it is an "optimisation" that will save nano seconds if that. That being said, if the methods were dealing with much larger objects it could potentially be something worth considering.

                      G 1 Reply Last reply
                      0
                      • K krieg38

                        The first methods creates two strings(s,f) and it should be more memory consuming.

                        G Offline
                        G Offline
                        Guffa
                        wrote on last edited by
                        #12

                        The two strings are created in both codes. The only difference is that the references to the strings are declared as variables in one code, while in the other code the compiler will create the references itself to handle the strings. --- b { font-weight: normal; }

                        1 Reply Last reply
                        0
                        • M MrEyes

                          Mike Dimmick wrote:

                          Nevertheless you should normally forget about micro-optimisations like this and concentrate on the areas that will have the biggest impact.

                          In this example, I agree it is an "optimisation" that will save nano seconds if that. That being said, if the methods were dealing with much larger objects it could potentially be something worth considering.

                          G Offline
                          G Offline
                          Guffa
                          wrote on last edited by
                          #13

                          As the only difference in coding is to keep references to the objects created, it doesn't matter how large the objects are. The size of a reference is always the same. When optimizing code it's very useful to know what the code really does, in order to find out what code is worth optimizing, and how. Example: int a = 42; string y = a + "," + a; That looks simple, but can be written much more efficient in this more lengthy way: int a = 42; string x = a.ToString(); string y = x + "," + x; The first code will be executed something like: int a = 42; string y = string.Concat(Number.FormatInt32((int)new Object(a), null, NumberFormatInfo.GetInstance(null)), (string)(object)",", Number.FormatInt32((int)new Object(a), null, NumberFormatInfo.GetInstance(null))); while the second code will be executed as: int a = 42; string x = Number.FormatInt32(a, null, NumberFormatInfo.GetInstance(null)); string y = string.Concat(x, ",", x); --- b { font-weight: normal; }

                          1 Reply Last reply
                          0
                          • L Lost User

                            The latter seems to be faster, is this correct?

                            D Offline
                            D Offline
                            Dave Kreskowiak
                            wrote on last edited by
                            #14

                            Probably a half second faster over the span of 1 million calls to it. But, of course, your milage may vary depending on your machine and how you drive it. RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome

                            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