|
-
April 1st, 2010, 03:51 PM
#1
Performance of Managed vs Unmanaged code
OK, so I haven't had very much experience and and still learning both C++ and C#. I decided to do a test of unmanaged C++ vs C#. I made what I believe to be close to identical code in both languages (but what do I know? lol.) I was hoping some of you may first of all, tell me if you see anything wrong with my code (bad practice, just plain bad code, whatever) and I hope you can also explain the differences I'm seeing.
C++ Program:
Code:
#include <iostream>
#include <string>
#include <sstream>
#include <windows.h>
using namespace std;
class Point
{
public:
int x, y;
Point();
Point(int x, int y);
friend Point operator+ (Point obj1, Point obj2);
string ToString();
};
int main()
{
long start, stop;
Point *pointArray = new Point[16000000];
start = GetTickCount();
for (int i = 0; i < 16000000; i++)
{
pointArray[i] = Point(i, i);
}
Point myPoint(1, 1);
for (int i = 0; i < 16000000; i++)
{
pointArray[i] = pointArray[i] + myPoint;
}
stop = GetTickCount();
cout << pointArray[0].ToString();
cout << stop - start << "ms";
cin.get();
return 0;
}
Point::Point()
{
this->x = 0;
this->y = 0;
}
Point::Point(int x, int y)
{
this->x = x;
this->y = y;
}
Point operator+(Point obj1, Point obj2)
{
return Point(obj1.x + obj2.x, obj1.y + obj2.y);
}
string Point::ToString()
{
ostringstream temp;
temp << "Point: x = " << x << ", y = " << y << endl;
return temp.str();
}
and here is my C# version:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(String[] args)
{
Stopwatch time = new Stopwatch();
Point[] pointArray = new Point[16000000];
time.Start();
for (Int32 i = 0; i < 16000000; i++)
{
pointArray[i] = new Point(i, i);
}
Point myPoint = new Point(1, 1);
for (Int32 i = 0; i < 16000000; i++)
{
pointArray[i] = pointArray[i] + myPoint;
}
time.Stop();
Console.WriteLine(pointArray[0].ToString());
Console.WriteLine("{0}ms", time.ElapsedMilliseconds);
Console.ReadLine();
}
}
class Point
{
public Int32 x, y;
public Point()
{
x = 0;
y = 0;
}
public Point(Int32 x, Int32 y)
{
this.x = x;
this.y = y;
}
public static Point operator +(Point obj1, Point obj2)
{
return new Point(obj1.x + obj2.x, obj1.y + obj2.y);
}
public override String ToString()
{
return String.Format("Point: x = {0}, y = {1}", this.x, this.y);
}
}
}
OK, so now that the code is out of the way, here are my observations:
C# Release version takes approximately 2560ms to execute.
C++ Debug version takes approximately 1060ms to execute.
C++ Release version takes approximately 32ms to execute.
Now, I assumed that C# would be slower. Is there anything I could do to make the C# code faster? Also, why is the C++ Release version so much ridiculously faster than both the C# and Debug version? I'm sure there could be some simple things I'm overlooking.
-
April 1st, 2010, 03:56 PM
#2
Re: Performance of Managed vs Unmanaged code
Also, why is the C++ Release version so much ridiculously faster than both the C# and Debug version?
The difference between debug and release is that the debug version does a lot more for debugging and error-trapping. Also, C++ is faster than C#.
-
April 1st, 2010, 04:04 PM
#3
Re: Performance of Managed vs Unmanaged code
 Originally Posted by Skizmo
The difference between debug and release is that the debug version does a lot more for debugging and error-trapping. Also, C++ is faster than C#.
Still, 80x seems a bit much. There's got to be a better explanation than "well C++ is faster than C#."
-
April 1st, 2010, 04:14 PM
#4
Re: Performance of Managed vs Unmanaged code
 Originally Posted by Chris_F
Still, 80x seems a bit much. There's got to be a better explanation than "well C++ is faster than C#."
Then post your C# question in the C# forum, and have the persons there answer why the C# code is slow.
Regards,
Paul McKenzie
-
April 1st, 2010, 04:16 PM
#5
Re: Performance of Managed vs Unmanaged code
Your C++ operator+ should take its arguments by const reference rather than by value.
You also need to delete[] the pointArray at the end, or better yet, use a std::vector<Point> instead of a dynamic array. In this case, you may want to time the difference between initializing the array to the full size and proceeding as you are, versus simply reserve()ing it to the full size and then push_back()ing each new Point in the first loop. The difference is that the latter should remove a useless default-constructor call.
-
April 1st, 2010, 04:17 PM
#6
Re: Performance of Managed vs Unmanaged code
 Originally Posted by Paul McKenzie
Then post your C# question in the C# forum, and have the persons there answer why the C# code is slow.
Regards,
Paul McKenzie
My questions are just as much having to do with C++ as C#. If I post this there, they can easily say the same thing to me. So perhaps someone can try helping me out here before I go posting this on every board.
-
April 1st, 2010, 04:20 PM
#7
Re: Performance of Managed vs Unmanaged code
 Originally Posted by Chris_F
My questions are just as much having to do with C++ as C#. If I post this there, they can easily say the same thing to me.
No they can't.
You are asking why your C# code is slow. So who else would be best to answer your question?
I know why the C++ code is fast -- if you want me to explain, then I will. If you want someone to explain why C# is slow, go ask the C# experts in the other forum (and there is only one forum here that has C# in its name). They may even reccommend (as Lindley did with the C++ version) as to how to speed up the C# code.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; April 1st, 2010 at 04:25 PM.
-
April 1st, 2010, 04:48 PM
#8
Re: Performance of Managed vs Unmanaged code
 Originally Posted by Lindley
Your C++ operator+ should take its arguments by const reference rather than by value.
You also need to delete[] the pointArray at the end, or better yet, use a std::vector<Point> instead of a dynamic array. In this case, you may want to time the difference between initializing the array to the full size and proceeding as you are, versus simply reserve()ing it to the full size and then push_back()ing each new Point in the first loop. The difference is that the latter should remove a useless default-constructor call.
like this?
Code:
Point Point::operator+(const Point &obj1) const
{
return Point(this->x + obj1.x, this->y + obj1.y);
}
-
April 1st, 2010, 05:08 PM
#9
Re: Performance of Managed vs Unmanaged code
That's one way to do it. The more usual approach is to implement operator+= as a member function, and then implement operator+ as a non-member, non-friend function in terms of +=.
Also, "this->" is unnecessary but not harmful there.
-
April 1st, 2010, 05:41 PM
#10
Re: Performance of Managed vs Unmanaged code
 Originally Posted by Chris_F
like this?
Code:
Point Point::operator+(const Point &obj1) const
{
return Point(this->x + obj1.x, this->y + obj1.y);
}
Here is a complete example, however this takes 150 ms on my "slow" PC:
Code:
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <windows.h>
using namespace std;
class Point
{
public:
int x, y;
Point();
Point(int x, int y);
friend Point operator+ (const Point& obj1, const Point& obj2);
Point& operator += (const Point& obj1);
void SetPoint(int x_, int y_);
string ToString();
};
struct PointSetter
{
void operator()(Point& thePoint) { ++cur; thePoint.SetPoint(cur, cur); }
int cur;
PointSetter(int StartNum=0) : cur(StartNum) { }
};
struct PointAdder
{
void operator()(Point& thePoint) { thePoint += m_Point; }
Point m_Point;
PointAdder() : m_Point(1,1) { }
};
int main()
{
long start, stop;
std::vector<Point> pointArray(16000000);
PointSetter ps;
PointAdder pa;
start = GetTickCount();
for_each(pointArray.begin(), pointArray.end(), ps);
for_each(pointArray.begin(), pointArray.end(), pa);
stop = GetTickCount();
cout << pointArray[0].ToString();
cout << stop - start << "ms";
cin.get();
return 0;
}
Point::Point() :x(0), y(0)
{ }
Point::Point(int x_, int y_) :x(x_), y(y_)
{ }
void Point::SetPoint(int x_, int y_)
{
x = x_;
y = y_;
}
Point operator+(const Point& obj1, const Point& obj2)
{
Point temp = obj1;
return temp += obj2;
}
Point& Point::operator+= (const Point& obj1)
{
x += obj1.x;
y += obj1.y;
return *this;
}
string Point::ToString()
{
ostringstream temp;
temp << "Point: x = " << x << ", y = " << y << endl;
return temp.str();
}
I added vector, a SetPoint, an operator +=, and used the algorithm functions to set and add the points.
Changing the code to this:
Code:
Point myPoint(1, 1);
for (int i = 0; i < 16000000; ++i)
pointArray[i].SetPoint(i,i);
for (int i = 0; i < 16000000; ++i)
pointArray[i] += myPoint;
replacing the algorithm functions didn't improve the time at all (not surprised). Actually, the time increased by 20 or so ms using the hand-coded for loops.
Regards,
Paul McKenzie
-
April 1st, 2010, 06:04 PM
#11
Re: Performance of Managed vs Unmanaged code
Thanks for that code, Paul.
-
April 1st, 2010, 06:35 PM
#12
Re: Performance of Managed vs Unmanaged code
 Originally Posted by Chris_F
Thanks for that code, Paul.
No problem.
Just remember that the C# gurus over in the C-sharp forum should help you with the speeding up of your C# code.
The issue is that C++ and C# look similar, so the tendency is to lump them as one "language", and therefore the temptation is to do a line-for-line translation from C++ to C# and vice-versa. However there are constructs in one language that are unknown by the the other language, constructs that may optimize things a little better.
For example, the algorithms helped the C++ code to optimize itself a little more -- I have no idea if C# has such things. Similarly, there may be constructs in C# that have no equivalence in C++ that would optimize the C# code.
Regards,
Paul McKenzie
-
April 2nd, 2010, 09:12 AM
#13
Re: Performance of Managed vs Unmanaged code
1) C++ has a considerably better optimiser than C#.
You can clearly see THAT part in action by the difference in the debug build and the release build.
It wouldn't surprise me at all that the optimising compiler sees the first loop can be skipped and changes it to a single loop setting the items to the value requested.
2) the C# code does a new for each item inserted. the C++ version does not.
memory allocation is a slow operation.
3) C# will spend part of it's time in the garbage collector. C++ doesn't have one. Garbage collection is pretty nifty, but it still takes a noticable amount of time.
-
April 2nd, 2010, 01:33 PM
#14
Re: Performance of Managed vs Unmanaged code
 Originally Posted by OReubens
1) C++ has a considerably better optimiser than C#.
You can clearly see THAT part in action by the difference in the debug build and the release build.
It wouldn't surprise me at all that the optimising compiler sees the first loop can be skipped and changes it to a single loop setting the items to the value requested.
My first guess was that 32ms time was achieved by skipping both loops (after all, only the first point value was ever used). But both loops are present in the optimized code 
The speed was achieved mostly, I believe, by inlining class member functions.
 Originally Posted by OReubens
3) C# will spend part of it's time in the garbage collector. C++ doesn't have one. Garbage collection is pretty nifty, but it still takes a noticable amount of time.
I don’t think that garbage collector will be involved in the measured time.
<edit> I am afraid I demonstrated my ignorance in C# and now want to retract my last statement (about GC)
Last edited by VladimirF; April 2nd, 2010 at 01:48 PM.
Reason: reconsideration
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
April 2nd, 2010, 02:03 PM
#15
Re: Performance of Managed vs Unmanaged code
 Originally Posted by Chris_F
C++ Release version takes approximately 32ms to execute.
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?
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|