locked
compositiontarget rendering slower on C++ than C#

    Question

  • I created two identical metro apps for C# and C++ that use CompositionTarget.Rendering. I animated 3000 <Image> elements and translated them in a Canvas. The c++ app was about 1/4 slower overall. The internal Frame Rate Counter control showed UI CPU Time bouncing between 10-30 milliseconds for both apps, but the c++ app was mostly in the 20's. The FPS was steadily lower for the C++ app.

     

    The C++ render loop looks like this:

    for (unsigned int index = 0; index < m_DrawObjects->Size; ++index)
        {
      auto drawObject = safe_cast<DrawObject^>(m_DrawObjects->GetAt(index));
      if (drawObject == nullptr)
       continue;

      drawObject->Draw();
     }

     

    The C# render loop looks like this:

    foreach (DrawObject drawObject in DrawObjects)
                {
                    drawObject.Draw();
                }

     

    There is no difference in the draw code as it just updates a TranslateTransform on the Image.RenderTransform control.

    I am guessing the difference is that c# is using an IList, and c++ is using a Platform::Vector.

    The expectation was the C++ code should be at least equal to the C# code. Is this a known performance problem?

    I can drop both project solutions somewhere if needed.

     

     

    Saturday, November 5, 2011 9:47 PM

Answers

  • Hey Rob,

    I am not able to download or test your code right now, but are you comparing the release-mode builds?

    I see that you mention not running "while in the debugger". But even if you run it without a debugger attached, if it's a debug-mode build, then the comparisons won't be accurate since you miss out on many code optimizations (more so for C++ than for C#).


    http://blog.voidnish.com
    • Marked as answer by RobHogue Sunday, November 6, 2011 10:29 PM
    Sunday, November 6, 2011 8:54 PM

All replies

  • Hi Rob,

    Please send the solutions to me:

    sharma dot raman at microsoft

    We will take a look.

    Thanks


    Raman Sharma | Program Manager, Visual C++ | @rasharm_msft

    (if my post has answered your question, please consider using the 'mark as answer' feature in the forums to help others)
    Sunday, November 6, 2011 3:03 AM
  • Raman, I sent you the solution in e-mail. I also am providing a link in case others want to verify the issue.

    http://www.rhogue.com/Microsoft/CompositionRenderRepro.zip

    thanks

    rhogue

    Sunday, November 6, 2011 4:22 AM
  • I created two identical metro apps for C# and C++ that use CompositionTarget.Rendering. I animated 3000 <Image> elements and translated them in a Canvas. The c++ app was about 1/4 slower overall. The internal Frame Rate Counter control showed UI CPU Time bouncing between 10-30 milliseconds for both apps, but the c++ app was mostly in the 20's. The FPS was steadily lower for the C++ app.

     

    The C++ render loop looks like this:

    for (unsigned int index = 0; index < m_DrawObjects->Size; ++index)
        {
      auto drawObject = safe_cast<DrawObject^>(m_DrawObjects->GetAt(index));
      if (drawObject == nullptr)
       continue;

      drawObject->Draw();
     }

     

    The C# render loop looks like this:

    foreach (DrawObject drawObject in DrawObjects)
                {
                    drawObject.Draw();
                }

     

    There is no difference in the draw code as it just updates a TranslateTransform on the Image.RenderTransform control.

    I am guessing the difference is that c# is using an IList, and c++ is using a Platform::Vector.

    The expectation was the C++ code should be at least equal to the C# code. Is this a known performance problem?

    I can drop both project solutions somewhere if needed.

     

     


    I've made some heuristic assumptions here.

    What is the type of m_DrawObjects? Is it an IVector<T>? If so, I believe that there's your problem. You are calling GetAt in the loop (also calling Size but that may be optimized out). Both are COM calls.

    In the C# version, the .NET collection is the one getting iterated (which is a copy of the COM collection). So while there's a one-time copy cost, the iteration itself will not have any COM calls.

    Try this. Copy the IVector<T> into a std::vector. Then iterate through the std::vector and you should see performance equal to or faster than the C# equivalent.


    http://blog.voidnish.com
    Sunday, November 6, 2011 1:42 PM
  • My FPS (Frames Per Second) for 3000 images on these samples are the following:

    C# = 82-84 fps

    C++ using std::vector = 78fps

    C++ using Platform::Vector = 68 fps

    The c# app is still beating C++. Below is a link to the code and folks are welcome to compare the apps on their systems to verify.

    http://www.rhogue.com/Microsoft/CompositionRenderRepro.zip

    If someone tweaks the C++ app to beat the C# app, drop a solution and I will happily verify it.

    Reminder : don't test FPS while in the debugger.

    Sunday, November 6, 2011 7:46 PM
  • Hey Rob,

    I am not able to download or test your code right now, but are you comparing the release-mode builds?

    I see that you mention not running "while in the debugger". But even if you run it without a debugger attached, if it's a debug-mode build, then the comparisons won't be accurate since you miss out on many code optimizations (more so for C++ than for C#).


    http://blog.voidnish.com
    • Marked as answer by RobHogue Sunday, November 6, 2011 10:29 PM
    Sunday, November 6, 2011 8:54 PM
  • You are right. For retail here are the results:

    C# WPF = 20 fps

    C# Metro = 82 fps

    c++ std::vector = 92

    c++ Platform::Vector = 90

    These results make more sense. I'll mark as answered.

    C# lagging by only 10% is very impressive.

     

     

    Sunday, November 6, 2011 10:29 PM
  • The Draw API should take most of the time, not the loop in which it is called.  And since both C# and C++ are calling the same API with the same implementation, I should expect similar results.

    The interesting thing is the speed up of C# from WPF to Metro from 20 to 82 FPS, which shows the efficiency of the implementation of the native Metro API I suppose.

     

    Sunday, November 6, 2011 10:52 PM
  • The interesting thing is the speed up of C# from WPF to Metro from 20 to 82 FPS, which shows the efficiency of the implementation of the native Metro API I suppose.


    As well as performance issues in WPF (which have always been a problem).
    http://blog.voidnish.com
    Thursday, November 10, 2011 1:19 PM