CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 23 of 23
  1. #16
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Performance of Managed vs Unmanaged code

    Quote Originally Posted by VladimirF View Post
    Complete off-topic: what kind of hardware do you test this on?
    On my (pretty decent) system, I am getting 78ms - 94ms results.
    Is it time for me to upgrade?
    I've got a reasonably fast (at least for its time) Core 2 Duo, and I'm getting 150 ms (VC 2008, release/maximize speed/_SECURE_SCL=0). So I'm in worse shape than you are.

    Regards,

    Paul McKenzie

  2. #17
    Join Date
    Aug 2008
    Posts
    902

    Re: Performance of Managed vs Unmanaged code

    The C++ optimized version indeed runs both loops. Playing around with the C# code a bit I was able to get it to run almost as fast as the C++ code my switching to a struct instead of a class and removing unnecessary NEW operations with alternatives, about 1.6x slower which is a lot better then 100x slower.

    I have a 4GHz Intel i5, so my times would probably be shorter than most.

  3. #18
    Join Date
    Apr 2010
    Posts
    1

    Re: Performance of Managed vs Unmanaged code

    The reason why the C# code is so slow is the fact that the Point is a reference type and not a value one. A value type items would be stored linearly inside the array allocated memory while the reference type, as someone else has already pointed out here, needs to allocate memory for every array item separately, so the array then holds, described in C++ terms, pointers to the objects instead of the objects themselves.
    Try to replace the "class" keyword by the "struct" keyword, you'll see that the performance will become very close to the performance of the C++ code. On my machine, the C++ code took 110ms to run, the C# took 138ms to run (both for release target).

    Thanks,

    Jan

  4. #19
    Join Date
    Jan 2007
    Posts
    5

    Re: Performance of Managed vs Unmanaged code

    There was an artificial neuralsystem app in C#.
    I have ported it to unmanaged (native) C++.
    It ran three times faster, in Release, unoptimized..
    Why?

    First, managed code uses intermediate language. The app is compiled to it and at the execution time this intermediate language is interpreted: the machine instructions are produced line-by-line in the time of execution (of course, this is more complicated, but idea is this.)
    This interpretation is completely absent in C++: the compilator and linker produce machine instructions well before execution.

    Second, most of local and global variables in C# are beeng placed on heap. It takes more processor time than using of stack in C++.

    Third, the C# garbage collector also takes some time to housekeeping the app memory. It should move some variables between heap tiers (there are four tiers on the heap), compact the memory and update memory block data.

    Fourth, I think that it is very Microsoft to sacrifice speed to convenience and easy of using C#.

  5. #20
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Performance of Managed vs Unmanaged code

    Despite the name, C# isn't very closely related to the C family. It has a lot more in common with Java, really.

  6. #21
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Performance of Managed vs Unmanaged code

    Quote Originally Posted by geoyar View Post
    There was an artificial neuralsystem app in C#.
    I have ported it to unmanaged (native) C++.
    It ran three times faster, in Release, unoptimized..
    Why?

    First, managed code uses intermediate language. The app is compiled to it and at the execution time this intermediate language is interpreted: the machine instructions are produced line-by-line in the time of execution (of course, this is more complicated, but idea is this.)
    This interpretation is completely absent in C++: the compilator and linker produce machine instructions well before execution.

    Second, most of local and global variables in C# are beeng placed on heap. It takes more processor time than using of stack in C++.

    Third, the C# garbage collector also takes some time to housekeeping the app memory. It should move some variables between heap tiers (there are four tiers on the heap), compact the memory and update memory block data.

    Fourth, I think that it is very Microsoft to sacrifice speed to convenience and easy of using C#.
    1° Actually. C# compiles to IML. At runtime, the IML is compiled to native code. Technically, this JIT compiler could do another optimizing phase here tailormade to the actual processor and OS the app is running on. I haven't kept up on details but I doubt this is currently happening, but it is a possibility this'll happen in the future.
    This is mainly why .NET code in general is so close to C++ compiled code, since it is in fact running native machine code. and NOT IML being interpreted each time.

    2° Again, this isn't strictly true. C# has stack based variables as well. It's just that you can't have objects, only pointers to allocated objects. A practice you don't HAVE to obey in C++, but which in general is good practice anyway to keep your stack consumption low.

    3° THIS is a major cause of performance differences. C++ offers you a much more tight control over memory allocation and deallocation. Garbage collection is good but it's still overhead that will kick in at times you may not want it to.

    4° Sorry, but this isn't "microsoft" at all. C# was designed to be a "RAD" convenience language, something a novice programmer can learn to use fast and effectively, and a language that would make it easier for experienced programmers to design the UI portion of their apps.
    As good as frameworks as MFC and QT are, designing a whole UI in those languages tends to be tedious. Doing the same in C# tends to be a lot easier.
    Part of that RAD approach is not having to remember to clean up stuff... In 'pure' languages, the cleanup is typically where the bulk of the bugs that make it in to release builds end up. It's simply harder to find them than results that aren't as you expect them to be.
    The very concept is present in Java as well. A language microsoft had nothing to do with (and which they now probably wished they never even made compilers and tools for).


    The gist of it... C# runs fast because it is ultimately native machine code once it's running.
    Well written C++ will always be faster than well written C#.

    I have seen very well written C++ code that did several times (yes, TIMES, not percentages) faster than an equally well written version in C#. There's just no substitute for having a lot of low level control when you want it to.

    C# (and to an extent managed C++) take a LOT of the grind out of writing code that deals with COM and a lot of the other new technologies. If you have a sizable application it's very well worth considering making the performance critical parts of your app in C++, and making the UI and the interfacing in C#.

    Part of being a good C++ programmer, is knowing when C++ isn't the best choice of language for a problem at hand.

  7. #22
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Performance of Managed vs Unmanaged code

    Performance isn't everything. In many cases, C# will have very acceptable performance to C++, so it becomes a question of ease of development.

    Consider passing data around using Message Queuing (MSMQ). Performance doesn't really matter in this fire and forget scenario (after all, there isn't going to be much perf different for a client pushing a message onto the queue between C++ and C#).

    In terms of development, let's look at the two approaches in code.

    C++:

    Code:
    HRESULT SendMulticast(
                          WCHAR * wszAddress
                          )
    {
    
      // Validate the input string.
      if (wszAddress == NULL)
      {
        return MQ_ERROR_INVALID_PARAMETER;
      }
    
    
      // Define the required variables and constants.
      const int NUMBEROFPROPERTIES = 5;              // Number of properties
      DWORD cPropId = 0;                             // Properties counter
    
      HRESULT hr = MQ_OK;                            // Return code
      HANDLE hQueue = NULL;                          // Queue handle
      
      
      // Define an MQMSGPROPS structure.
      MQMSGPROPS msgProps;
      MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];
      MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];
      HRESULT aMsgStatus[NUMBEROFPROPERTIES];
      
      
      // Specify the message properties to be sent.
      aMsgPropId[cPropId] = PROPID_M_LABEL;               // Property ID
      aMsgPropVar[cPropId].vt = VT_LPWSTR;                // Type indicator
      aMsgPropVar[cPropId].pwszVal = L"test message";     // The message's label
      cPropId++;
    
    
      // Initialize the MQMSGPROPS structure.
      msgProps.cProp = cPropId;                           // Number of message properties
      msgProps.aPropID = aMsgPropId;                      // IDs of the message properties
      msgProps.aPropVar = aMsgPropVar;                    // Values of the message properties
      msgProps.aStatus = aMsgStatus;                      // Error reports
      
      
      // Generate a multicast address format name.
      WCHAR * wszFormatName = NULL;
      DWORD dwFormatNameLength = 0;
      dwFormatNameLength = wcslen(wszAddress) + 11;
      wszFormatName = new WCHAR[wcslen(wszAddress) + 11];
      if (wszFormatName == NULL)
      {
        return MQ_ERROR_INSUFFICIENT_RESOURCES;
      }
      memset(wszFormatName, 0, dwFormatNameLength*sizeof(WCHAR));
    
      // ************************************
      // You must concatenate the string "MULTICAST=" and wszAddress into 
      // the wszFormatName buffer.
      // wszFormatName = "MULTICAST=" + wszAddress
      // If the format name is too long for the buffer, return 
      // FALSE.
      // ************************************
    
      // Open the queues using the multicast address format name.
      hr = MQOpenQueue(
                       wszFormatName,                     // Multicast address format name
                       MQ_SEND_ACCESS,                    // Access mode
                       MQ_DENY_NONE,                      // Share mode
                       &hQueue                            // OUT: queue handle
                       );
      // Free the memory that was allocated for the format name string.
      delete [] wszFormatName;
    
    
      // Handle any error returned by MQOpenQueue.
      if (FAILED(hr))
      {
        return hr;
      }
      
      
      // Send the message to the queues listening to the multicast
      // address.
      hr = MQSendMessage(
                         hQueue,                         // Queue handle
                         &msgProps,                      // Message property structure
                         MQ_NO_TRANSACTION               // No transaction
                         );
    
      if (FAILED(hr))
      {
        MQCloseQueue(hQueue);
        return hr;
      }
      
      
      // Close the queue.
      hr = MQCloseQueue(hQueue);
      
      return hr;
    }
    C#:

    Code:
    //Send the message the queue
    using(  var  mq  =  newMessageQueue( "FORMATNAME:MULTICAST=224.1.2.3:8001" ) )
    {
      mq.Send( "Test message" );
    }


  8. #23
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Performance of Managed vs Unmanaged code

    Quote Originally Posted by OReubens View Post
    2° Again, this isn't strictly true. C# has stack based variables as well. It's just that you can't have objects, only pointers to allocated objects. A practice you don't HAVE to obey in C++, but which in general is good practice anyway to keep your stack consumption low.
    On the contrary, putting objects on the stack is a very good practice in C++. A well-designed object will keep itself small by using the heap internally as necessary, so stack overflow isn't a problem; but cleanup is also automated since you just let the stack unroll and everything is taken care of.

    Furthermore, the "use the heap internally" design caveat is in many cases trivial, since you can foist off the actual heap management on STL containers and the like.

Page 2 of 2 FirstFirst 12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured