Collections in .NET (C#)

M

mitch

if pc is a collection object (i.e. derives from CollectionBase) and
contains objects which have a GetX() accesser and I do the followingtwo
things:

p = pc[0];
for(int n = 0; n < 100000000; n++)
{
double x = p.Getx();
}

the loops runs in 0.3 seconds

if however I have:

for(int n = 0; n < 100000000; n++)
{
double x = pc[0].Getx();
}

it take 6 seconds!

What's going on. Are .NET collections this slow or am I missing
something?

Thanks for any advice on implementing a fast collection in c#,
Mitch.
 
M

Miha Markic [MVP C#]

One obvious difference is that in the second case you are using this[]
property, so what does your implementation of this[] look like?
And btw, if you are on .net 2 you are better off using generic collections.
 
J

John J. Hughes II

I changed you code to run and use generics and got the following results:

struct tmpP
{
public double Getx()
{
return 0.00;
}
}

private void testRun()
{
List<tmpP> pc = new List<tmpP>();
for(int n=0; n<100000000; n++)
pc.Add(new tmpP());

System.Diagnostics.Debug.WriteLine("direct");
DateTime start = DateTime.Now;

tmpP p = pc[0];
for(int n = 0; n < 100000000; n++)
{
double x = p.Getx();
}
System.Diagnostics.Debug.WriteLine(DateTime.Now - start);

System.Diagnostics.Debug.WriteLine("index");
start = DateTime.Now;
for(int n = 0; n < 100000000; n++)
{
double x = pc[0].Getx();
}
System.Diagnostics.Debug.WriteLine(DateTime.Now - start);

System.Diagnostics.Debug.WriteLine("foreach");
start = DateTime.Now;
foreach(tmpP tp in pc)
{
double x = tp.Getx();
}
System.Diagnostics.Debug.WriteLine(DateTime.Now - start);
}

direct
00:00:03.6471240
index
00:00:02.4937600
foreach
00:00:02.3223140
 
M

mitch

Miha said:
One obvious difference is that in the second case you are using this[]
property, so what does your implementation of this[] look like?
And btw, if you are on .net 2 you are better off using generic collections.

--
Miha Markic [MVP C#]
RightHand .NET consulting & development www.rthand.com
Blog: http://cs.rthand.com/blogs/blog_with_righthand/

if pc is a collection object (i.e. derives from CollectionBase) and
contains objects which have a GetX() accesser and I do the followingtwo
things:

p = pc[0];
for(int n = 0; n < 100000000; n++)
{
double x = p.Getx();
}

the loops runs in 0.3 seconds

if however I have:

for(int n = 0; n < 100000000; n++)
{
double x = pc[0].Getx();
}

it take 6 seconds!

What's going on. Are .NET collections this slow or am I missing
something?

Thanks for any advice on implementing a fast collection in c#,
Mitch.

Hi, thanks for your replies.

Firstly:

I am using visual studio 2003. Program Add/Remove manager is showing me
that I have both .NET 1.1 and .NET 2.0 installed but vis stu 2003
doesn't know about the namespace System.Collections.Generic Can vis stu
2003 use .NET 2.0 and if so how can I get it to use it given that it is
installed?

Finally:

In Visual Studio 6 using MFC container class I have:

typedef CTypedPtrArray<CPtrArray,CMyObject*> CMyObjectsPtrArray;

Where a CMyOject just has a GetX() method which returns 5.0

I then have the following:

for(int n = 0; n < 100000000; n++)
{
CMyObject* pMyObject = m_objectsArray[0];

double x = pMyObject->GetX();
}

It executes in 0.3 seconds.

Is .NET performance really that much worse. John J. Hughes II's post
here and my experience given prior put .NET at around the 4 second mark
(over 10 times slower!) is that really the case or can I use something
other the a CollectionBase class or use the same in a better way? Or am
I just going to have to accept such a speed decrease?

Thanks for any comments,

Mitch.
 
J

Joanna Carter [TeamB]

<[email protected]> a écrit dans le message de (e-mail address removed)...

| Is .NET performance really that much worse. John J. Hughes II's post
| here and my experience given prior put .NET at around the 4 second mark
| (over 10 times slower!) is that really the case or can I use something
| other the a CollectionBase class or use the same in a better way? Or am
| I just going to have to accept such a speed decrease?

CollectionBase stores everything as an object, this means that everything
has to be cast to/from your type when doing anything at all with the items
in the list. If you are deriving from CollectionBase to store value types or
structs, then you will not only have the castring overhead, you will also
have the boxing/unboxing overhead to consider.

IMO .NET 1 collections were too slow to contemplate, for the above reasons.
However, .NET 2.0 genreic collections are blazingly fast. But you will have
to move to VS2005 to be able to use generics.

Joanna
 
G

Greg Young

Mitch are you running your code with the debugger? The debugger will disable
JIT optimizations.

The reason thy the C++ code runs the same speed as the first bit of C# code,
I would guess is that the compiler hoists your assignment from within the
loop outside of the loop (thus producing the same code as the first
example). I do not remember off the top of my head if JIT optimizations will
catch this case (although it should be pretty easy to test)

You could also make this code significantly faster by using unsafe code if
it is in a space that absolutely requires it.

Cheers,

Greg Young
MVP - C#
http://geekswithblogs.net/gyoung
One obvious difference is that in the second case you are using this[]
property, so what does your implementation of this[] look like?
And btw, if you are on .net 2 you are better off using generic
collections.

--
Miha Markic [MVP C#]
RightHand .NET consulting & development www.rthand.com
Blog: http://cs.rthand.com/blogs/blog_with_righthand/

if pc is a collection object (i.e. derives from CollectionBase) and
contains objects which have a GetX() accesser and I do the followingtwo
things:

p = pc[0];
for(int n = 0; n < 100000000; n++)
{
double x = p.Getx();
}

the loops runs in 0.3 seconds

if however I have:

for(int n = 0; n < 100000000; n++)
{
double x = pc[0].Getx();
}

it take 6 seconds!

What's going on. Are .NET collections this slow or am I missing
something?

Thanks for any advice on implementing a fast collection in c#,
Mitch.

Hi, thanks for your replies.

Firstly:

I am using visual studio 2003. Program Add/Remove manager is showing me
that I have both .NET 1.1 and .NET 2.0 installed but vis stu 2003
doesn't know about the namespace System.Collections.Generic Can vis stu
2003 use .NET 2.0 and if so how can I get it to use it given that it is
installed?

Finally:

In Visual Studio 6 using MFC container class I have:

typedef CTypedPtrArray<CPtrArray,CMyObject*> CMyObjectsPtrArray;

Where a CMyOject just has a GetX() method which returns 5.0

I then have the following:

for(int n = 0; n < 100000000; n++)
{
CMyObject* pMyObject = m_objectsArray[0];

double x = pMyObject->GetX();
}

It executes in 0.3 seconds.

Is .NET performance really that much worse. John J. Hughes II's post
here and my experience given prior put .NET at around the 4 second mark
(over 10 times slower!) is that really the case or can I use something
other the a CollectionBase class or use the same in a better way? Or am
I just going to have to accept such a speed decrease?

Thanks for any comments,

Mitch.
 
J

John J. Hughes II

Switching to 2003 you can get better performance if you stop using an object
and cast directly to the given value. Below is a converted sample show the
results which are even faster then 2005 with generics. Just sort of depends
on how much fexablity you have.

struct tmpP
{
public double Getx()
{
return 0.00;
}
}

private static void testRun()
{
tmpP[] pc = new tmpP[100000000];

System.Diagnostics.Debug.WriteLine("direct");
DateTime start = DateTime.Now;

tmpP p = pc[0];
for(int n = 0; n < 100000000; n++)
{
double x = p.Getx();
}
System.Diagnostics.Debug.WriteLine(DateTime.Now - start);

System.Diagnostics.Debug.WriteLine("index");
start = DateTime.Now;
for(int n = 0; n < 100000000; n++)
{
double x = pc[0].Getx();
}
System.Diagnostics.Debug.WriteLine(DateTime.Now - start);

System.Diagnostics.Debug.WriteLine("foreach");
start = DateTime.Now;
foreach(tmpP tp in pc)
{
double x = tp.Getx();
}
System.Diagnostics.Debug.WriteLine(DateTime.Now - start);
}


direct
00:00:01.1845360
index
00:00:01.3559820
foreach
00:00:01.6365300

Regards,
John
 
W

Willy Denoyette [MVP]

Note that you run this code as a debug build, which means with most JIT
optimizations turned off. Running the release build makes no sense either,
the JIT compiler may hoists the for loops, or completely ignore the
result(the result x is loop scoped, so not used outside the loop).

Willy.

| Switching to 2003 you can get better performance if you stop using an
object
| and cast directly to the given value. Below is a converted sample show
the
| results which are even faster then 2005 with generics. Just sort of
depends
| on how much fexablity you have.
|
| struct tmpP
| {
| public double Getx()
| {
| return 0.00;
| }
| }
|
| private static void testRun()
| {
| tmpP[] pc = new tmpP[100000000];
|
| System.Diagnostics.Debug.WriteLine("direct");
| DateTime start = DateTime.Now;
|
| tmpP p = pc[0];
| for(int n = 0; n < 100000000; n++)
| {
| double x = p.Getx();
| }
| System.Diagnostics.Debug.WriteLine(DateTime.Now - start);
|
| System.Diagnostics.Debug.WriteLine("index");
| start = DateTime.Now;
| for(int n = 0; n < 100000000; n++)
| {
| double x = pc[0].Getx();
| }
| System.Diagnostics.Debug.WriteLine(DateTime.Now - start);
|
| System.Diagnostics.Debug.WriteLine("foreach");
| start = DateTime.Now;
| foreach(tmpP tp in pc)
| {
| double x = tp.Getx();
| }
| System.Diagnostics.Debug.WriteLine(DateTime.Now - start);
| }
|
|
| direct
| 00:00:01.1845360
| index
| 00:00:01.3559820
| foreach
| 00:00:01.6365300
|
| Regards,
| John
|
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top