Re: Managed vs Unmanaged Bare Bones Performance Test



You can probably speed up the C# code a bit, but it will most likely still perform less than C++. So, if performance is REALLY the ONLY issue, choose C++.

Cha-ching! Another problem solved!

Now, the real question is "Is performance REALLY the ONLY issue"? Most likely the answer, despite protestations of suits, is not the real issue. In my years as a consultant, I have found that buying an additional server is almost always cheaper than hiring additional C++ programmers. Now, there are certainly instances where performance is the ONLY issue or where testing reveals that a specific portion of code is too slow and needs help. In those cases, boost the perf of the component and compile as a library. If you do that you reduce the number of employees needed to maintain the code and the number of rock stars you need in your organization.

Please note: there are instances where performance trumps all other aspects of development. In general, however, maintenance (cost of dev team) is a lot higher than cost to boost perf.

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA
http://gregorybeamer.spaces.live.com

*********************************************
Think outside the box!
*********************************************
"adhingra" <adhingra@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message news:40A7D63A-948F-4609-8558-91BDEA73E13D@xxxxxxxxxxxxxxxx
At our company we are currently at a decisive point to choose between managed
and unmanaged code on the basis of their performance. I have read stuff about
this on various blogs and other websites. Then I decided to take my own test
as I am more concerned with basic performance at this point.

By basic I mean, just the basic stuff inside the CLR i.e. function calling
cost, for loop, variable declaration, etc. Let us not consider GC, memory
allocation costs, etc.

To my surprise the managed code I generated in my test through C# was
lagging behind to a considerable degree when compared with the code generated
by the C++ compiler.

I was wondering if someone can take a quick look at this and tell me why is
this the case. I was under the assumption, once the JIT happens, the CLR
virtual machine and JIT will give the same performance as native C++ compiler
does (as we are talking basic stuff only - no objects, just pure language
constructs and primitive data types).

I created two sample console applications (one in C# and other in C++). They
both call a function passing an int by value from inside a for loop. Nothing
happens inside the function. I used QueryPerformance.... apis for
measurement. (Code is pasted at the bottom of this posting).

Here are the results (for release mode running from console, with default
settings in the IDE)

C# Test for loop (50000 iterations) 0.000023931 (23 micro seconds)
C++ Test for loop (50000 iterations) 0.000000350 (0.35 micro seconds)

So its like C++ compiler is about 20 times faster than the managed CLR
Jitter. And if I also remove time taken for the QueryPerf...... apis then the
diff is even more

Can anyone please elaborate.

Thanks
adhingra

===========================================
C# Code PROGRAM.CS
===========================================

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
class Program
{
//API declarations for frequency timers
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);

static long m_lStart = 0, m_lStop = 0, m_lFreq = 0;
static long m_lOverhead = 0;
static decimal m_mTotalTime = 0;

static void Main(string[] args)
{
//get the CPU frequency
QueryPerformanceFrequency(ref m_lFreq);

//record the overhead for calling the performance counter API
QueryPerformanceCounter(ref m_lStart);
QueryPerformanceCounter(ref m_lStop);

m_lOverhead = m_lStop - m_lStart;

Console.WriteLine("Starting with a simple For Loop calling a
simple function");

QueryPerformanceCounter(ref m_lStart);
for (int i = 0; i < 50000; i++)
{
Run(i);
}
QueryPerformanceCounter(ref m_lStop);

long lDiff = m_lStop - m_lStart;
Console.WriteLine(lDiff);
//Comment or Uncomment the overhead lines to see the times drop
//
//if (lDiff > m_lOverhead)
//{
// lDiff = lDiff - m_lOverhead;
//}

m_mTotalTime = ((Decimal)lDiff)/((Decimal)m_lFreq);
Console.WriteLine(m_mTotalTime);

Console.WriteLine("Press Enter to Continue");
Console.ReadLine();
}

static void Run(int i)
{
//Console.WriteLine(i);
}
}
}


===============================================
C++ Code ConsoleApp.cpp
===============================================

// ConsoleApp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

void Run(int i)
{
//printf("%d\n",i);
}

int _tmain(int argc, _TCHAR* argv[])
{
LARGE_INTEGER m_start, m_stop, m_freq;
::QueryPerformanceFrequency(&m_freq);

//record the overhead for calling the performance counter API
::QueryPerformanceCounter(&m_start);
::QueryPerformanceCounter(&m_stop);

LONGLONG m_overhead = m_stop.QuadPart - m_start.QuadPart;
m_start.QuadPart = 0;
m_stop.QuadPart = 0;

printf("%s\n","Starting with a simple For Loop calling a simple function");

QueryPerformanceCounter(&m_start);
for (int i = 0; i < 50000; i++)
{
Run(i);
}
QueryPerformanceCounter(&m_stop);

LONGLONG lDiff = m_stop.QuadPart - m_start.QuadPart;
printf("%d\n",lDiff);
//Comment or Uncomment the overhead lines to see the times drop
//
//if (lDiff > m_overhead)
//{
// lDiff = lDiff - m_overhead;
//}

double totalTime = ((double)lDiff) / ((double)m_freq.QuadPart);
printf("%15.15f\n",totalTime);

printf("%s", "Press Enter to Continue");

int c = getchar();
return 0;
}



.



Relevant Pages

  • Managed vs Unmanaged Bare Bones Performance Test
    ... just the basic stuff inside the CLR i.e. function calling ... Here are the results (for release mode running from console, ... //record the overhead for calling the performance counter API ...
    (microsoft.public.dotnet.framework.clr)
  • Managed vs Unmanaged Bare Bones Performance Test
    ... just the basic stuff inside the CLR i.e. function calling ... Here are the results (for release mode running from console, ... //record the overhead for calling the performance counter API ...
    (microsoft.public.dotnet.framework)
  • Re: Managed vs Unmanaged Bare Bones Performance Test
    ... virtual machine and JIT will give the same performance as native C++ compiler ... both call a function passing an int by value from inside a for loop. ... //record the overhead for calling the performance counter API ...
    (microsoft.public.dotnet.framework.clr)
  • Re: Managed vs Unmanaged Bare Bones Performance Test
    ... just the basic stuff inside the CLR i.e. function calling ... both call a function passing an int by value from inside a for loop. ... //record the overhead for calling the performance counter API ...
    (microsoft.public.dotnet.framework)
  • Re: Assembly string functions in i386 libc
    ... of string functions on i386? ... for the usual overhead for string instructions). ... The cmpb in this takes 2 cycles, but the loop overhead takes no more ... versions using the string instructions are much ...
    (freebsd-arch)

Loading