Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / November 2006

Tip: Looking for answers? Try searching our database.

ArrayList without Boxing and UnBoxing

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Peter Olcott - 03 Nov 2006 20:03 GMT
How can I create an ArrayList in the older version of .NET that does not require
the expensive Boxing and UnBoxing operations?

In my case it will be an ArrayList of structures of ordinal types.

Thanks.
Mythran - 03 Nov 2006 20:13 GMT
> How can I create an ArrayList in the older version of .NET that does not
> require the expensive Boxing and UnBoxing operations?
>
> In my case it will be an ArrayList of structures of ordinal types.
>
> Thanks.

You would need to create a collection class yourself and implement the
necessary methods/properties (including IEnumerable).  The internal
implementation, to avoid boxing, would need to be an array of your
value-type values.  (MyStructure[] mArray).  You would also need to
implement your own handling of adding and removing from the array (note:
probably want to create an array large enough to handle the most common size
or most common maximum size) and only increase the size when you run out of
elements in the internal array.

HTH,
Mythran
Bruce Wood - 03 Nov 2006 20:29 GMT
> How can I create an ArrayList in the older version of .NET that does not require
> the expensive Boxing and UnBoxing operations?
>
> In my case it will be an ArrayList of structures of ordinal types.

1. Have you determined that boxing and unboxing are in fact causing
significant performance degradation in your application? That is, are
you trying to optimize a priori, or do you already have a performance
problem you're trying to resolve?

2. Does it have to be an ArrayList? Or can you use an array? Do you
need to dynamically add / remove items?

If you do indeed have a performance problem caused by boxing and
unboxing, and you need a dynamic structure, then you'll have to build
your own.
Bill Rodenbaugh - 03 Nov 2006 20:34 GMT
What you are describing is called a Strongly Typed Collection.
http://www.google.com/search?q=strongly+typed+collections

You should be able to find a number of free add-ins that will make
creating them alot easier.
http://www.google.com/search?q=strongly+typed+collection+add-in

If you are dealing with strings you can use the StringCollection and
StringDictionary in the System.Collections.Specialized namespace.
http://msdn2.microsoft.com/en-gb/library/32c13e62(vs.80,en-us).aspx

> How can I create an ArrayList in the older version of .NET that does not require
> the expensive Boxing and UnBoxing operations?
>
> In my case it will be an ArrayList of structures of ordinal types.
>
> Thanks.
Bruce Wood - 03 Nov 2006 21:34 GMT
Those are good links, Bill, but they don't address the OP's problem.

Remember that the original question was how to avoid boxing and
unboxing. Any collection that derives from CollectionBase will store
Object, and so require boxing and unboxing for value types.

The only way to avoid boxing overhead is to write your own collection
class that wraps an array of the value type in question. However,
before going down that road, it's important to determine that boxing is
indeed a problem.

> What you are describing is called a Strongly Typed Collection.
> http://www.google.com/search?q=strongly+typed+collections
[quoted text clipped - 11 lines]
> >
> > In my case it will be an ArrayList of structures of ordinal types.
Peter Olcott - 03 Nov 2006 22:16 GMT
> Those are good links, Bill, but they don't address the OP's problem.
>
[quoted text clipped - 6 lines]
> before going down that road, it's important to determine that boxing is
> indeed a problem.

My response time can not exceed 1/10 second. The class is currently implemented
in C++ using std::vector. I can not afford any degradation in the performance of
this class when ported to .NET.

>> What you are describing is called a Strongly Typed Collection.
>> http://www.google.com/search?q=strongly+typed+collections
[quoted text clipped - 12 lines]
>> >
>> > In my case it will be an ArrayList of structures of ordinal types.
Arne Vajhøj - 03 Nov 2006 22:21 GMT
>> Remember that the original question was how to avoid boxing and
>> unboxing. Any collection that derives from CollectionBase will store
[quoted text clipped - 8 lines]
> in C++ using std::vector. I can not afford any degradation in the performance of
> this class when ported to .NET.

You can box and unbox a lot of variables before it is noticeable in
1/10 second time intervals.

Arne
Peter Olcott - 03 Nov 2006 23:46 GMT
>>> Remember that the original question was how to avoid boxing and
>>> unboxing. Any collection that derives from CollectionBase will store
[quoted text clipped - 13 lines]
>
> Arne

By what factor does a simple integer comparison in a fixed array of integers to
single integer take longer when boxing an unboxing is adding? (Note the simple
comparision itself takes one machine clock). Even if unboxing takes only one
machine clock, we have now doubled the time required.
Mark Wilden - 04 Nov 2006 00:29 GMT
> By what factor does a simple integer comparison in a fixed array of
> integers to single integer take longer when boxing an unboxing is adding?
> (Note the simple comparision itself takes one machine clock). Even if
> unboxing takes only one machine clock, we have now doubled the time
> required.

Doubling a tiny amount of time still results in a tiny amount of time. You'd
have to do a proper performance analysis before determining that
boxing/unboxing was significant.

///ark
Peter Olcott - 04 Nov 2006 02:34 GMT
>> By what factor does a simple integer comparison in a fixed array of integers
>> to single integer take longer when boxing an unboxing is adding? (Note the
[quoted text clipped - 6 lines]
>
> ///ark

How many clock cycles does one unboxing operation take?
Arne Vajhøj - 05 Nov 2006 00:42 GMT
>> Doubling a tiny amount of time still results in a tiny amount of time. You'd
>> have to do a proper performance analysis before determining that
>> boxing/unboxing was significant.

> How many clock cycles does one unboxing operation take?

The little program attached below gives on my PC:

integer array: 0,046875
object array: 1,515625

With the uncertainty always present in that kind of micro
benchmarks, that says:

7 million box+unbox per second

Your stuff runs in 0.1 second. If we say that 1/100 overhead
is the acceptable, then you can box and unbox 7000 times in
your code.

Arne

using System;
using System.Collections.Generic;

namespace E
{
    public class MainClass
    {
        private const int N = 10000000;
        public static void Main(string[] args)
        {
            int[] ia = new int[N];
            DateTime dt1 = DateTime.Now;
            for(int i = 0; i < N; i++)
            {
                ia[i] = i;
            }
            for(int i = 0; i < N; i++)
            {
                if(ia[i] != i)
                {
                    Console.WriteLine("Oops");
                    Environment.Exit(1);
                }
            }
            DateTime dt2 = DateTime.Now;
            object[] oa = new object[N];
            Console.WriteLine("integer array: " + (dt2 - dt1).TotalSeconds);
            DateTime dt3 = DateTime.Now;
            for(int i = 0; i < N; i++)
            {
                oa[i] = i;
            }
            for(int i = 0; i < N; i++)
            {
                if((int)oa[i] != i)
                {
                    Console.WriteLine("Oops");
                    Environment.Exit(1);
                }
            }
            DateTime dt4 = DateTime.Now;
            Console.WriteLine("object array: " + (dt4 - dt3).TotalSeconds);
            Console.ReadKey();
        }
    }
}
Peter Olcott - 05 Nov 2006 03:04 GMT
That would make it infeasible. Generics completely bypass boxing and unboxing,
right?

>>> Doubling a tiny amount of time still results in a tiny amount of time. You'd
>>> have to do a proper performance analysis before determining that
[quoted text clipped - 64 lines]
> }
> }
Bruce Wood - 05 Nov 2006 08:08 GMT
> That would make it infeasible. Generics completely bypass boxing and unboxing,
> right?

Yes. Generics allow the compiler to create aggregate structures that
contain value types directly, rather than structures that contain
Object and so require boxing.

That's why I asked why you weren't using .NET 2.0: generics solve your
problem nicely, but they're only available starting in .NET 2.0.
Peter Olcott - 05 Nov 2006 13:53 GMT
>> That would make it infeasible. Generics completely bypass boxing and
>> unboxing,
[quoted text clipped - 3 lines]
> contain value types directly, rather than structures that contain
> Object and so require boxing.

I need the C# equivalent of std::vector. It must be able to dynamically grow in
size, and it must not have any more overhead than an unmanaged array of struct.
Can generics handle this?

> That's why I asked why you weren't using .NET 2.0: generics solve your
> problem nicely, but they're only available starting in .NET 2.0.
Arne Vajhøj - 05 Nov 2006 18:40 GMT
> I need the C# equivalent of std::vector. It must be able to dynamically grow in
> size, and it must not have any more overhead than an unmanaged array of struct.
> Can generics handle this?

I would say that the two requirements:
1) be able to dynamically grow
2) must not have any more overhead than an unmanaged array
are in conflict.

Nothing is free.

I extended my previous posted example and get:

                    save   retrieve
integer array   :   0,08   0,03
object array    :   3,05   0,08
array list      :   4,67   0,16
generic list    :   0,31   0,05

Arne
Peter Olcott - 05 Nov 2006 19:45 GMT
>> I need the C# equivalent of std::vector. It must be able to dynamically grow
>> in
[quoted text clipped - 8 lines]
>
> Nothing is free.

Unmanaged array access costs no more than unmanaged array access, I think it is
about one clock.

> I extended my previous posted example and get:
>
[quoted text clipped - 5 lines]
>
> Arne
Arne Vajhøj - 05 Nov 2006 22:53 GMT
>>> I need the C# equivalent of std::vector. It must be able to dynamically grow
>>> in
[quoted text clipped - 10 lines]
> Unmanaged array access costs no more than unmanaged array access, I think it is
> about one clock.

The functionality offered by a list will cost. Maybe only in adding
and not in getting. But it will cost.

That should be rather obvious.

Arne
Peter Olcott - 06 Nov 2006 05:23 GMT
>>>> I need the C# equivalent of std::vector. It must be able to dynamically
>>>> grow in
[quoted text clipped - 13 lines]
> The functionality offered by a list will cost. Maybe only in adding
> and not in getting. But it will cost.

std::vector provides access time equal to the access time of unmanaged array
access, yet can dynamically grow.
Does .NET have anything with EXACTLY these performance characteristics?

> That should be rather obvious.
>
> Arne
Jon Skeet [C# MVP] - 06 Nov 2006 07:15 GMT
> > The functionality offered by a list will cost. Maybe only in adding
> > and not in getting. But it will cost.
>
> std::vector provides access time equal to the access time of unmanaged array
> access, yet can dynamically grow.
> Does .NET have anything with EXACTLY these performance characteristics?

Frankly, I doubt that std::vector provides that, to be honest. Assuming
it's an array + size, you need to do a size check before the array
access, so there's a performance penalty there, even if it's really
small.

Certainly I haven't seen anything in .NET which has *no* performance
penalty over using arrays. You could probably write a list which would
return potentially bad data rather than throwing the appropriate
exception if, say, you had a backing array of size 5, a list of size 2,
and asked for element 4. I'd rather have correctness with the tiny
performance penalty though...

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Peter Olcott - 06 Nov 2006 13:49 GMT
>> > The functionality offered by a list will cost. Maybe only in adding
>> > and not in getting. But it will cost.
[quoted text clipped - 7 lines]
> access, so there's a performance penalty there, even if it's really
> small.

No there is no size check, and this cost is not be really small, it at least
doubles the access time.

> Certainly I haven't seen anything in .NET which has *no* performance
> penalty over using arrays. You could probably write a list which would
> return potentially bad data rather than throwing the appropriate
> exception if, say, you had a backing array of size 5, a list of size 2,
> and asked for element 4. I'd rather have correctness with the tiny
> performance penalty though...
Willy Denoyette [MVP] - 06 Nov 2006 16:12 GMT
| >> > The functionality offered by a list will cost. Maybe only in adding
| >> > and not in getting. But it will cost.
[quoted text clipped - 10 lines]
| No there is no size check, and this cost is not be really small, it at least
| doubles the access time.

This is definitely not true, consider following small sample:

#include <vector>
int main(int argc, char *argv[])
{
  size_t size = 100;
  std::vector<int> array(size);    // make room for 10 integers,
  // and initialize them to 0
  // do something with them:
  for(int i=0; i<size; ++i){
  array[i] = i;
  }
  // break here, disassembly follows
  int v = array[55];
  return 0;
}

comments added [n]

004025e8 85ff            test    edi,edi    [1]
004025ea 740a            je      vect!main+0x56 (004025f6)
004025ec 2bdf            sub     ebx,edi [2]
004025ee c1fb02          sar     ebx,2  [3]
004025f1 83fb37          cmp     ebx,37h  [4]
004025f4 7705            ja      vect!main+0x5b (004025fb)
004025f6 e8f1070000      call    vect!_invalid_parameter_noinfo (00402dec)
004025fb 8b8fdc000000    mov     ecx,dword ptr [edi+0DCh]
ds:0023:00324c3c=00000037 [5]

[1] checks array base pointer for null (non initialized)
[2] calculate length of array in bytes (edi = base, edx points to past end
of array)
[3] convert to length in int's (divide by 4)
[4] index < length of array
[5] move int at edi+55 -> ecx

You see, there is a pointer validation check and a bounds check for each
access. This accounts for 6 instructions, supposed index is within bounds.
Exactly the same is done in .NET when accessing array elements.

Willy.
Peter Olcott - 06 Nov 2006 17:22 GMT
> | >> > The functionality offered by a list will cost. Maybe only in adding
> | >> > and not in getting. But it will cost.
[quoted text clipped - 51 lines]
> You see, there is a pointer validation check and a bounds check for each
> access. This accounts for 6 instructions, supposed index is within bounds.

You are not supposed to get range checking unless you explicitly ask for it by
invoking the std::vector:at(n) member function.

> Exactly the same is done in .NET when accessing array elements.
>
> Willy.
Willy Denoyette [MVP] - 06 Nov 2006 18:16 GMT
| > | >> > The functionality offered by a list will cost. Maybe only in adding
| > | >> > and not in getting. But it will cost.
[quoted text clipped - 54 lines]
| You are not supposed to get range checking unless you explicitly ask for it by
| invoking the std::vector:at(n) member function.

This is an implementation detail. The std library as supplied by MSFT
(Dinkumware's implementation)) since 7.1 does range checking, don't know
about other iplementations though. Point is that you should not rely on
this, the standard does not enforce operator[] to be 'unchecked' AFAIK.
The major difference between operator[] and at() access is that the former
calls a "crt debugger" hook  followed by a 'drwatson' call, while the latter
throws an "out_of_range" exception.

Willy.
Willy Denoyette [MVP] - 06 Nov 2006 18:49 GMT
|| > | >> > The functionality offered by a list will cost. Maybe only in
| adding
[quoted text clipped - 72 lines]
|
| Willy.

Forgot to mention that this behavior can be turned of by means of
the -D_SECURE_SCL switch or in code using:
#define _SECURE_SCL 0
Note that by doing so, you throw away all security related enhancements.

Willy.
Arne Vajhøj - 07 Nov 2006 03:09 GMT
> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>> The functionality offered by a list will cost. Maybe only in adding
[quoted text clipped - 3 lines]
> access, yet can dynamically grow.
> Does .NET have anything with EXACTLY these performance characteristics?

Hm.

GCC 3.2 with -O3:

integer array     0.06   0.03
vector            0.33   0.06

BCB 5.6:

integer array     0.06   0.03
vector            0.33   0.05

VC++ 7.1 with /Ox:

integer array     0.06   0.03
vector            0.44   0.05

Results fluctuate a bit, but at average integer array
is faster than vector.

Arne

PS: Ask for code if interested.
Peter Olcott - 07 Nov 2006 13:09 GMT
>> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>>> The functionality offered by a list will cost. Maybe only in adding
[quoted text clipped - 27 lines]
>
> PS: Ask for code if interested.

What are the two columns?
Arne Vajhøj - 08 Nov 2006 00:50 GMT
>>> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>>>> The functionality offered by a list will cost. Maybe only in adding
[quoted text clipped - 27 lines]
>
> What are the two columns?

Storing and retrieving.

Arne
Peter Olcott - 08 Nov 2006 12:33 GMT
>>>> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>>>>> The functionality offered by a list will cost. Maybe only in adding
[quoted text clipped - 31 lines]
>
> Arne

Is that storing using push_back(), or storing using operator[] ?
I would think that the former would be much slower than the latter.
Arne Vajhøj - 10 Nov 2006 02:24 GMT
>>>>> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>>>>>> The functionality offered by a list will cost. Maybe only in adding
[quoted text clipped - 21 lines]
>>>> Results fluctuate a bit, but at average integer array
>>>> is faster than vector.

>>> What are the two columns?

>> Storing and retrieving.

> Is that storing using push_back(), or storing using operator[] ?
> I would think that the former would be much slower than the latter.

push_back

[] will crash unless the array is preallocated - in which case
a simple array could just as well be used.

Arne
Peter Olcott - 15 Nov 2006 15:58 GMT
>>>>>> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>>>>>>> The functionality offered by a list will cost. Maybe only in adding
[quoted text clipped - 35 lines]
>
> Arne

When I am talking about array access, I am talking about reading from the array.
If .NET takes more than 50% more time to read from an array of scalar types, it
would be unacceptable for my application. With Boxing and UnBoxing we have much
more than a 50% cost penalty. I am not sure about the cost penalty (if any) for
generics.
Bill Butler - 15 Nov 2006 16:24 GMT
> When I am talking about array access, I am talking about reading from
> the array. If .NET takes more than 50% more time to read from an array
> of scalar types, it would be unacceptable for my application. With
> Boxing and UnBoxing we have much more than a 50% cost penalty. I am
> not sure about the cost penalty (if any) for generics.

As has been suggested in the past, You should set up a realistic proof
of concept to see if this is the issue that you think it is. If, after
testing, you determine that the performance hit is unacceptable, THEN
you should start working on ways around the issue.

   Bill
Peter Olcott - 15 Nov 2006 22:59 GMT
>> When I am talking about array access, I am talking about reading from the
>> array. If .NET takes more than 50% more time to read from an array of scalar
[quoted text clipped - 8 lines]
>
>    Bill

Its not worth spending the learning curve that is required. If I could know in
advance that benchmarks prove that the read access time to scalar types is
comparable to that to read access time of unmanaged array access, then it might
be worth the learning curve to pursue further.
Bill Butler - 15 Nov 2006 23:53 GMT
<snip>
> Its not worth spending the learning curve that is required. If I could
> know in advance that benchmarks prove that the read access time to
> scalar types is comparable to that to read access time of unmanaged
> array access, then it might be worth the learning curve to pursue
> further.

Is your current App running so close to the edge that you cannot afford
any spare clock cycles?

Doing a quick proof of concept shouldn't be THAT time consuming. Perhaps
you really can't afford the overhead, but you will never know if you
don't do a test

Bill
Peter Olcott - 16 Nov 2006 01:27 GMT
> <snip>
>> Its not worth spending the learning curve that is required. If I could know
[quoted text clipped - 4 lines]
> Is your current App running so close to the edge that you cannot afford any
> spare clock cycles?

Its real-time, every clock cycle counts.

> Doing a quick proof of concept shouldn't be THAT time consuming. Perhaps you
> really can't afford the overhead, but you will never know if you don't do a
> test

It requires buying a $500.00 compiler and learning .NET and C#. This is far too
much commitment when this can simply be a question answered by someone that
already knows the answer. In theory there is no reason why .NET generics, need
to be any slower at all than std::vector on read access.  In theory there is no
reason why C# must be any slower than C++. Sometimes theory and practice do not
correspond.

> Bill
Ben Newsam - 16 Nov 2006 01:40 GMT
> In theory there is no reason why .NET generics, need
>to be any slower at all than std::vector on read access.  In theory there is no
>reason why C# must be any slower than C++. Sometimes theory and practice do not
>correspond.

I am only learning the beginnings of C#, but even I recognize that it
is bound to be slower than C or C++. I am willing to allow that as
long as I get something back in return. I am still hopeful about that,
but the jury is still out...

Signature

Posted via a free Usenet account from http://www.teranews.com

Peter Olcott - 16 Nov 2006 02:25 GMT
>> In theory there is no reason why .NET generics, need
>>to be any slower at all than std::vector on read access.  In theory there is
[quoted text clipped - 7 lines]
> long as I get something back in return. I am still hopeful about that,
> but the jury is still out...

.NET and C# do have an excellent design, and probably will be able to provide
the same performance as unmanaged native code eventually, if they do not already
do so.  I need to know how well they do this now. The official word from
Microsoft is that managed C++ is faster than managed C#.
Arne Vajhøj - 16 Nov 2006 02:45 GMT
> I am only learning the beginnings of C#, but even I recognize that it
> is bound to be slower than C or C++. I am willing to allow that as
> long as I get something back in return. I am still hopeful about that,
> but the jury is still out...

Well - that is not obvious to me.

Why should optimization at compile time be better
than optimization first time run ?

Arne
Ben Newsam - 16 Nov 2006 08:43 GMT
>> I am only learning the beginnings of C#, but even I recognize that it
>> is bound to be slower than C or C++. I am willing to allow that as
[quoted text clipped - 5 lines]
>Why should optimization at compile time be better
>than optimization first time run ?

Faster. I wouldn't know about better.

Signature

Posted via a free Usenet account from http://www.teranews.com

Peter Olcott - 16 Nov 2006 15:26 GMT
>>> I am only learning the beginnings of C#, but even I recognize that it
>>> is bound to be slower than C or C++. I am willing to allow that as
[quoted text clipped - 7 lines]
>
> Faster. I wouldn't know about better.

There are two factors: when you have the original source code more information
is provided so that a greater degree of changes can be made, and still derive
the same result. From a marketability point of view slow compile times effect
fewer users than slower run times, so you have more time to do a better job at
compile time. Neither of these two things is a limitation for .NET.
Arne Vajhøj - 17 Nov 2006 02:04 GMT
>>>> I am only learning the beginnings of C#, but even I recognize that it
>>>> is bound to be slower than C or C++. I am willing to allow that as
[quoted text clipped - 11 lines]
> fewer users than slower run times, so you have more time to do a better job at
> compile time. Neither of these two things is a limitation for .NET.

I think most optimizing compiler do convert source to an
intermediate form before optimizing anyway, so the source info
is lost when the optimization is done.

Arne
Peter Olcott - 17 Nov 2006 03:24 GMT
>>>>> I am only learning the beginnings of C#, but even I recognize that it
>>>>> is bound to be slower than C or C++. I am willing to allow that as
[quoted text clipped - 18 lines]
>
> Arne

The source code itself it lost, but, not the richer semantic structure that is
provided by the source.
Arne Vajhøj - 16 Nov 2006 01:42 GMT
> It requires buying a $500.00 compiler and learning .NET and C#. This is far too
> much commitment when this can simply be a question answered by someone that
> already knows the answer. In theory there is no reason why .NET generics, need
> to be any slower at all than std::vector on read access.  In theory there is no
> reason why C# must be any slower than C++. Sometimes theory and practice do not
> correspond.

The C# compiler is free.

Actually my tests showed the same overhead for read from C# List<int>
and C++ vector<int>. About 50% for both !

Arne
Peter Olcott - 16 Nov 2006 02:35 GMT
>> It requires buying a $500.00 compiler and learning .NET and C#. This is far
>> too much commitment when this can simply be a question answered by someone
[quoted text clipped - 9 lines]
>
> Arne

integer array: 0,046875
object array: 1,515625
32-fold more time?

How does this compare when we are testing read access between an integer array,
and the fastest way that .NET can provide integer array access, generics?
Arne Vajhøj - 16 Nov 2006 02:44 GMT
>>> It requires buying a $500.00 compiler and learning .NET and C#. This is far
>>> too much commitment when this can simply be a question answered by someone
[quoted text clipped - 15 lines]
> How does this compare when we are testing read access between an integer array,
> and the fastest way that .NET can provide integer array access, generics?

You are looking at the combined store and retrive numbers.

The split up were:

                    save   retrieve
integer array   :   0,08   0,03
object array    :   3,05   0,08
array list      :   4,67   0,16
generic list    :   0,31   0,05

Arne
Peter Olcott - 16 Nov 2006 03:06 GMT
>>>> It requires buying a $500.00 compiler and learning .NET and C#. This is far
>>>> too much commitment when this can simply be a question answered by someone
[quoted text clipped - 28 lines]
>
> Arne

I did not understand these numbers:
(1) Is the comma intended to take tha place of a decimal point, or are there
four different numbers per line ?
(2) What are these numbers clocks per operation?  Seconds per fixed number of
operations ?
(3) How do they compare to std::vector ?
Arne Vajhøj - 17 Nov 2006 02:02 GMT
> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>> You are looking at the combined store and retrive numbers.
[quoted text clipped - 12 lines]
> (1) Is the comma intended to take tha place of a decimal point, or are there
> four different numbers per line ?

Comma is decimal point in the locale I am using.

> (2) What are these numbers clocks per operation?  Seconds per fixed number of
> operations ?

The last. But it should really not matter. Only that smaller is better.
And that should be obvious from the results.

> (3) How do they compare to std::vector ?

A posted 8-10 posts previous:

GCC 3.2 with -O3:

integer array     0.06   0.03
vector            0.33   0.06

BCB 5.6:

integer array     0.06   0.03
vector            0.33   0.05

VC++ 7.1 with /Ox:

integer array     0.06   0.03
vector            0.44   0.05

Arne
Peter Olcott - 17 Nov 2006 03:34 GMT
>> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>>> You are looking at the combined store and retrive numbers.
[quoted text clipped - 41 lines]
>
> Arne

So then the answer is clear, .NET without generics can be unacceptably slow,
58-fold slower than unmanaged array storage and 500% slower than unmanaged array
retrieval, but, with generics very comparable to std::vector. I would suppose
that we could greatly speed up the std::vector storage by using resize(), and
operator[]() instead of push_back(). With my time critical processing, I know
the size in advance.
Arne Vajhøj - 18 Nov 2006 02:22 GMT
> So then the answer is clear, .NET without generics can be unacceptably slow,
> 58-fold slower than unmanaged array storage and 500% slower than unmanaged array
> retrieval, but, with generics very comparable to std::vector. I would suppose
> that we could greatly speed up the std::vector storage by using resize(), and
> operator[]() instead of push_back(). With my time critical processing, I know
> the size in advance.

If you know the size then why not just allocate a good
oldfashioned array ?

Arne
Peter Olcott - 18 Nov 2006 02:32 GMT
>> So then the answer is clear, .NET without generics can be unacceptably slow,
>> 58-fold slower than unmanaged array storage and 500% slower than unmanaged
[quoted text clipped - 7 lines]
>
> Arne

I would estimate that might not be one of the .NET best practices. My purpose
here on this forum is to evaluate the feasibility of using .NET for my screen
recognition system. It looks likes your benchmarks derive a passing score for
.NET that includes generics, and a failing score for earlier versions. Thanks
for all your help.
Bruce Wood - 18 Nov 2006 07:17 GMT
> >> So then the answer is clear, .NET without generics can be unacceptably slow,
> >> 58-fold slower than unmanaged array storage and 500% slower than unmanaged
[quoted text clipped - 9 lines]
>
> I would estimate that might not be one of the .NET best practices.

Good grief.

Your original post stated that the solution had to work on "older
versions of .NET" and implied that you required a dynamic memory
structure. Now, after mountains of back-and-forth, it turns out that
you have no problem with using .NET 2.0 and that you know the size up
front.

If you'd told us those two things at the outset it would have saved a
lot of time and effort.

If you know the size up front, use an array. Period. Dynamic structures
cost: you get what you pay for, and you pay for what you get. This has
nothing to do with .NET as such: it's just a basic tenet of computing.

> My purpose here on this forum is to evaluate the feasibility of using .NET for my screen
> recognition system. It looks likes your benchmarks derive a passing score for
> .NET that includes generics, and a failing score for earlier versions.

Only for dynamic memory structures. If you can use a fixed-size array
then any version of .NET will yield similar (and speedy) results. If
you require a dynamic structure then .NET 1.1 forces you to box and
unbox values (unless you roll your own, naturally). .NET 2.0 introduces
generics which get around the boxing issue.

But for heaven's sake, next time state the situation clearly, so that
it doesn't take 50 or so posts to arrive at a conclusion!
Peter Olcott - 18 Nov 2006 17:11 GMT
I have to top post because somehow you managed to turn quoting off.
Can  allocating an ordinary array, be done through the managed heap? If it can
not be done using the managed heap, then wouldn't allocating unmanaged memory be
considered a poor practice in terms of good .NET design?

There are two different facets to my problem, one requiring the array to
dynamically grow, and the other most time critical one, knows its size in
advance. Even the one that is required to dynamically grow, must do this
relatively quickly, thus can not take the boxing / unboxing overhead. I wanted
to see if I could adapt my system to .NET using my current compiler, the answer
is no. The next level question is can my system be adapted to .NET at all, the
answer is yes if I use generics.

Peter Olcott wrote:
> > Peter Olcott wrote:
> >> So then the answer is clear, .NET without generics can be unacceptably
[quoted text clipped - 11 lines]
>
> I would estimate that might not be one of the .NET best practices.

Good grief.

Your original post stated that the solution had to work on "older
versions of .NET" and implied that you required a dynamic memory
structure. Now, after mountains of back-and-forth, it turns out that
you have no problem with using .NET 2.0 and that you know the size up
front.

If you'd told us those two things at the outset it would have saved a
lot of time and effort.

If you know the size up front, use an array. Period. Dynamic structures
cost: you get what you pay for, and you pay for what you get. This has
nothing to do with .NET as such: it's just a basic tenet of computing.

> My purpose here on this forum is to evaluate the feasibility of using .NET for
> my screen
> recognition system. It looks likes your benchmarks derive a passing score for
> .NET that includes generics, and a failing score for earlier versions.

Only for dynamic memory structures. If you can use a fixed-size array
then any version of .NET will yield similar (and speedy) results. If
you require a dynamic structure then .NET 1.1 forces you to box and
unbox values (unless you roll your own, naturally). .NET 2.0 introduces
generics which get around the boxing issue.

But for heaven's sake, next time state the situation clearly, so that
it doesn't take 50 or so posts to arrive at a conclusion!
Bruce Wood - 18 Nov 2006 18:10 GMT
> Can  allocating an ordinary array, be done through the managed heap? If it can
> not be done using the managed heap, then wouldn't allocating unmanaged memory be
> considered a poor practice in terms of good .NET design?

Who said anything about unmanaged memory? I'm talking about using a
regular, boring managed array. Fixed-size arrays in .NET can be of any
type, including value types, and so required no boxing and unboxing in
order to store value types. There is no need to use unmanaged arrays.

> There are two different facets to my problem, one requiring the array to
> dynamically grow, and the other most time critical one, knows its size in
> advance.

The use a dynamic structure for the first and a vanilla fixed-size
array for the second. Using a fixed-size array will certainly bring
speed benefits.

> Even the one that is required to dynamically grow, must do this
> relatively quickly, thus can not take the boxing / unboxing overhead. I wanted
> to see if I could adapt my system to .NET using my current compiler, the answer
> is no. The next level question is can my system be adapted to .NET at all, the
> answer is yes if I use generics.

No, the answer is even better than that. The answer is that you can
achieve a high-speed dynamic structure in .NET 1.1, but you have to
program it yourself. Remember that ArrayList is just a wrapper around
an array that, when you attempt to add one element too many,
reallocates the array and copies the contents. You can write your own
ArrayList specific to your value type that will have no boxing /
unboxing overhead. The only thing that .NET 2.0 gives you is the
ability to use the dynamic data structures provided by the .NET
Framework without incurring boxing / unboxing overhead.
Peter Olcott - 18 Nov 2006 18:46 GMT
>> Can  allocating an ordinary array, be done through the managed heap? If it
>> can
[quoted text clipped - 33 lines]
> ability to use the dynamic data structures provided by the .NET
> Framework without incurring boxing / unboxing overhead.

Actually it must be any array of struct of scalar types, 8-bit, 16-bit, and
32-bit integers, all unsigned.

struct MyType {
 uint     One;
 ushort Two;
 byte    Three;
};

How do I go about creating the equivalent of a std::vector<MyType> that does not
ever have boxing and unboxing overhead?
Arne Vajhøj - 18 Nov 2006 21:24 GMT
> Actually it must be any array of struct of scalar types, 8-bit, 16-bit, and
> 32-bit integers, all unsigned.
[quoted text clipped - 7 lines]
> How do I go about creating the equivalent of a std::vector<MyType> that does not
> ever have boxing and unboxing overhead?

If you know the size:

MyType[] myarray = new MyType[noelm];

If you don't know the size and are on .NET 2.0:

List<MyType> mylist = new List<MyType>();

Arne
Peter Olcott - 18 Nov 2006 22:26 GMT
>> Actually it must be any array of struct of scalar types, 8-bit, 16-bit, and
>> 32-bit integers, all unsigned.
[quoted text clipped - 17 lines]
>
> Arne

Bruce said that this could be done using .NET 1.1
>you can achieve a high-speed dynamic structure in .NET 1.1, but you have to
>program it yourself.
Arne Vajhøj - 18 Nov 2006 23:07 GMT
>> If you know the size:
>>
[quoted text clipped - 9 lines]
>> you can achieve a high-speed dynamic structure in .NET 1.1, but you have to
>> program it yourself.

You can not make a fast generic one in 1.1, but you can make a fast
one specific for your type.

Arne
Peter Olcott - 18 Nov 2006 23:39 GMT
>>> If you know the size:
>>>
[quoted text clipped - 14 lines]
>
> Arne

That is all that I need. How hard would this be? I already wrote a complete
std::vector from scratch, (for a C++ compiler lacking this capability) does it
require this same amount of programming?
Arne Vajhøj - 19 Nov 2006 00:04 GMT
> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>> You can not make a fast generic one in 1.1, but you can make a fast
[quoted text clipped - 3 lines]
> std::vector from scratch, (for a C++ compiler lacking this capability) does it
> require this same amount of programming?

Probably less.

If you only need a constructor + an Add method + an indexer
then it can not be many lines of code.

Arne
Peter Olcott - 19 Nov 2006 00:39 GMT
>> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>>> You can not make a fast generic one in 1.1, but you can make a fast
[quoted text clipped - 10 lines]
>
> Arne
It also must dynamically re-allocate when it needs to grow in size.
Arne Vajhøj - 19 Nov 2006 02:59 GMT
>>> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>>>> You can not make a fast generic one in 1.1, but you can make a fast
[quoted text clipped - 8 lines]
>>
> It also must dynamically re-allocate when it needs to grow in size.

Yes - but that is inside the Add method.

Arne
Bruce Wood - 19 Nov 2006 08:33 GMT
> >> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
> >>> You can not make a fast generic one in 1.1, but you can make a fast
[quoted text clipped - 11 lines]
> > Arne
> It also must dynamically re-allocate when it needs to grow in size.

I do not vouch for the following: I wrote it off the top of my head, so
the syntax may not even be 100%, but to give you an idea:

public class MyValueTypeVector
{
   private MyValueType[] _vector;
   private int _upperBound;

   public MyValudTypeVector() : this(10) {  }

   public MyValueTypeVector(int initialCapacity)
   {
       this._vector = new MyValueType[initialCapacity];
       this._upperBound = 0;
   }

   public MyValueType this[int index]
   {
       get { return this._vector[index]; }
       set { this._vector[index] = value; }
   }

   public int Length { get { return this._upperBound; } }

   public void Add(MyValueType newMember)
   {
       if (this._upperBound >= this._vector.Length - 1)
       {
           MyValueType newVector[] = new
MyValueType[this._vector.Length * 2];
           for (int i = 0; i < this._vector.Length; i++)
           {
               newVector[i] = this._vector[i];
           }
           this._vector = newVector;
       }
       this._vector[this._upperBound] = newMember;
       this._upperBound += 1;
   }
}

Some notes:

1. Notice that the indexer does no bounds check. That is, it is
possible for client code to read/write "past the end of" the array"
(above the upperBounds limit) so long as it doesn't write outside the
physical capacity of the allocated array. This is for speed. Adding the
check will cost one additional comparison per reference / assignment,
and would look like this:

public MyValueType this[int index]
{
   get
   {
       if (index >= this._upperBounds) { throw new
IndexOutOfBoundsException(...); }
       return this._vector[index];
   }
   set
   {
       if (index >= this._upperBounds) { throw new
IndexOutOfBoundsException(...); }
       this._vector[index] = value;
   }
}

Even this omits the index < 0 check, as this will throw an exception on
the array access itself. Again, not the prettiest, but we're going for
speed, here.

2. The original indexer is sufficiently simple that the compiler /
JITter should in-line the calls, reducing indexed access to the
"vector" to a simple array access (one bounds comparison, one address
calculation, and one read or write) with no method call overhead. If it
turns out tha the JITter does not in-line calls, you could always make
_vector public and access it directly via myVector.Vector[i], which is
ugly but possible. You shouldn't have to do this, though, because the
compiler really should in-line such a simple indexer as the first one.
The second with the bounds check probably wouldn't be in-lined.

3. The class is _not_ thread-safe. In particular, the reallocation
operation is _not_ atomic and cannot be made atomic without slowing the
whole thing down tremendously by introducing locks around the indexer
getter and setter and the Add operation including reallocation. I
assume that you're not multi-threading.
Peter Olcott - 19 Nov 2006 14:34 GMT
It looks like you have found the best possible solution to every aspect of my
original question. I am assuming that generics are equivalent to C++ templates
so that this solution could be adapted to become a generic solution. I am
assuming by what you said that C# does not have the equivalent the [inline]
keyword.

Peter Olcott wrote:
> > Peter Olcott wrote:
> >> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
[quoted text clipped - 12 lines]
> > Arne
> It also must dynamically re-allocate when it needs to grow in size.

I do not vouch for the following: I wrote it off the top of my head, so
the syntax may not even be 100%, but to give you an idea:

public class MyValueTypeVector
{
   private MyValueType[] _vector;
   private int _upperBound;

   public MyValudTypeVector() : this(10) {  }

   public MyValueTypeVector(int initialCapacity)
   {
       this._vector = new MyValueType[initialCapacity];
       this._upperBound = 0;
   }

   public MyValueType this[int index]
   {
       get { return this._vector[index]; }
       set { this._vector[index] = value; }
   }

   public int Length { get { return this._upperBound; } }

   public void Add(MyValueType newMember)
   {
       if (this._upperBound >= this._vector.Length - 1)
       {
           MyValueType newVector[] = new
MyValueType[this._vector.Length * 2];
           for (int i = 0; i < this._vector.Length; i++)
           {
               newVector[i] = this._vector[i];
           }
           this._vector = newVector;
       }
       this._vector[this._upperBound] = newMember;
       this._upperBound += 1;
   }
}

Some notes:

1. Notice that the indexer does no bounds check. That is, it is
possible for client code to read/write "past the end of" the array"
(above the upperBounds limit) so long as it doesn't write outside the
physical capacity of the allocated array. This is for speed. Adding the
check will cost one additional comparison per reference / assignment,
and would look like this:

public MyValueType this[int index]
{
   get
   {
       if (index >= this._upperBounds) { throw new
IndexOutOfBoundsException(...); }
       return this._vector[index];
   }
   set
   {
       if (index >= this._upperBounds) { throw new
IndexOutOfBoundsException(...); }
       this._vector[index] = value;
   }
}

Even this omits the index < 0 check, as this will throw an exception on
the array access itself. Again, not the prettiest, but we're going for
speed, here.

2. The original indexer is sufficiently simple that the compiler /
JITter should in-line the calls, reducing indexed access to the
"vector" to a simple array access (one bounds comparison, one address
calculation, and one read or write) with no method call overhead. If it
turns out tha the JITter does not in-line calls, you could always make
_vector public and access it directly via myVector.Vector[i], which is
ugly but possible. You shouldn't have to do this, though, because the
compiler really should in-line such a simple indexer as the first one.
The second with the bounds check probably wouldn't be in-lined.

3. The class is _not_ thread-safe. In particular, the reallocation
operation is _not_ atomic and cannot be made atomic without slowing the
whole thing down tremendously by introducing locks around the indexer
getter and setter and the Add operation including reallocation. I
assume that you're not multi-threading.
Bruce Wood - 24 Nov 2006 17:39 GMT
> It looks like you have found the best possible solution to every aspect of my
> original question. I am assuming that generics are equivalent to C++ templates
> so that this solution could be adapted to become a generic solution. I am
> assuming by what you said that C# does not have the equivalent the [inline]
> keyword.

After all of this back-and-forth about array access speed....

You DO realize that C# is a garbage-collected language, like Java, and
that at any time the GC can decide to kick in and do garbage
collection?

I know that people DO use C# for real-time applications, so you may
want to read up on how they ensure that particular paths through the
code (which are the paths with real-time deadlines to meet) aren't
interrupted by the GC.
Peter Olcott - 24 Nov 2006 19:27 GMT
>> It looks like you have found the best possible solution to every aspect of my
>> original question. I am assuming that generics are equivalent to C++
[quoted text clipped - 13 lines]
> code (which are the paths with real-time deadlines to meet) aren't
> interrupted by the GC.

I would think that this might be something like forcing GC before you enter the
time critical path? I don't think that GC will be a problem for my most time
critical operation. For this operation I know the required size in advance for
the operation requiring the largest amount of memory, and the other operations
need so little memory that I could allocate the maximum required of this memory
in advance too, if I have to.

I will implement the original solution in unmanaged C++.  Because of all of the
help that I have received here it looks like I will be able to transform this
original solution into a .NET implementation. In other words the .NET
architecture has passed the required feasibility tests. It looks like .NET can
provide the required performance, one way or another.

Also I just went back and reviewed, the help that you provided was apparently
the most useful of all help that was provided, thanks again.
Peter Olcott - 19 Nov 2006 14:41 GMT
public MyValueType this[uint index]  // does this eliminate the possibility of
index < 0 ?
   {
       get { return this._vector[index]; }
       set { this._vector[index] = value; }
   }

Peter Olcott wrote:
> > Peter Olcott wrote:
> >> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
[quoted text clipped - 12 lines]
> > Arne
> It also must dynamically re-allocate when it needs to grow in size.

I do not vouch for the following: I wrote it off the top of my head, so
the syntax may not even be 100%, but to give you an idea:

public class MyValueTypeVector
{
   private MyValueType[] _vector;
   private int _upperBound;

   public MyValudTypeVector() : this(10) {  }

   public MyValueTypeVector(int initialCapacity)
   {
       this._vector = new MyValueType[initialCapacity];
       this._upperBound = 0;
   }

   public MyValueType this[int index]
   {
       get { return this._vector[index]; }
       set { this._vector[index] = value; }
   }

   public int Length { get { return this._upperBound; } }

   public void Add(MyValueType newMember)
   {
       if (this._upperBound >= this._vector.Length - 1)
       {
           MyValueType newVector[] = new
MyValueType[this._vector.Length * 2];
           for (int i = 0; i < this._vector.Length; i++)
           {
               newVector[i] = this._vector[i];
           }
           this._vector = newVector;
       }
       this._vector[this._upperBound] = newMember;
       this._upperBound += 1;
   }
}

Some notes:

1. Notice that the indexer does no bounds check. That is, it is
possible for client code to read/write "past the end of" the array"
(above the upperBounds limit) so long as it doesn't write outside the
physical capacity of the allocated array. This is for speed. Adding the
check will cost one additional comparison per reference / assignment,
and would look like this:

public MyValueType this[int index]
{
   get
   {
       if (index >= this._upperBounds) { throw new
IndexOutOfBoundsException(...); }
       return this._vector[index];
   }
   set
   {
       if (index >= this._upperBounds) { throw new
IndexOutOfBoundsException(...); }
       this._vector[index] = value;
   }
}

Even this omits the index < 0 check, as this will throw an exception on
the array access itself. Again, not the prettiest, but we're going for
speed, here.

2. The original indexer is sufficiently simple that the compiler /
JITter should in-line the calls, reducing indexed access to the
"vector" to a simple array access (one bounds comparison, one address
calculation, and one read or write) with no method call overhead. If it
turns out tha the JITter does not in-line calls, you could always make
_vector public and access it directly via myVector.Vector[i], which is
ugly but possible. You shouldn't have to do this, though, because the
compiler really should in-line such a simple indexer as the first one.
The second with the bounds check probably wouldn't be in-lined.

3. The class is _not_ thread-safe. In particular, the reallocation
operation is _not_ atomic and cannot be made atomic without slowing the
whole thing down tremendously by introducing locks around the indexer
getter and setter and the Add operation including reallocation. I
assume that you're not multi-threading.
Bruce Wood - 19 Nov 2006 19:45 GMT
> public MyValueType this[uint index]  // does this eliminate the possibility of
> index < 0 ?
>     {
>         get { return this._vector[index]; }
>         set { this._vector[index] = value; }
>     }

Yes, but you will have to mark the method as non-CLS compliant because
some .NET languages don't support unsigned types. No biggie unless
you're planning on calling the code from another .NET language.

And no, C# has no "inline" indication. That is left entirely up to the
compiler and the JITter.

Yes, C# generics offer similar functionality to C++ templates, although
the former are compiler constructs while the latter are
text-substitution constructs, which introduces some subtle differences.
Nonetheless, you can think of them as the "same thing" for basic usage
purposes.
Peter Olcott - 19 Nov 2006 19:53 GMT
>> public MyValueType this[uint index]  // does this eliminate the possibility
>> of
[quoted text clipped - 16 lines]
> Nonetheless, you can think of them as the "same thing" for basic usage
> purposes.

Now all that remains is to see if your get/set code mentioned above is placed
inline.
Bruce Wood - 20 Nov 2006 02:54 GMT
> >> public MyValueType this[uint index]  // does this eliminate the possibility
> >> of
[quoted text clipped - 19 lines]
> Now all that remains is to see if your get/set code mentioned above is placed
> inline.

I know that the compiler inlines getters and setters that do nothing
but fetch and assign a corresponding field. I don't see why an indexer
would be any different.
Peter Olcott - 20 Nov 2006 05:30 GMT
>> >> public MyValueType this[uint index]  // does this eliminate the
>> >> possibility
[quoted text clipped - 24 lines]
> but fetch and assign a corresponding field. I don't see why an indexer
> would be any different.

Yes, but, this issue will remain unresolved until I know for sure. One of the
rules that I strictly enforce is never make any assumptions. How could the
answer to this question be empirically verified?
Jon Skeet [C# MVP] - 20 Nov 2006 07:11 GMT
> > I know that the compiler inlines getters and setters that do nothing
> > but fetch and assign a corresponding field. I don't see why an indexer
[quoted text clipped - 3 lines]
> rules that I strictly enforce is never make any assumptions. How could the
> answer to this question be empirically verified?

Compile a simple test app, run it under cordbg, and look at the
assembly generated.

You'll need to turn optimisations on everywhere though.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Peter Olcott - 20 Nov 2006 17:30 GMT
>> > I know that the compiler inlines getters and setters that do nothing
>> > but fetch and assign a corresponding field. I don't see why an indexer
[quoted text clipped - 6 lines]
> Compile a simple test app, run it under cordbg, and look at the
> assembly generated.

Is it possible to look at the actual Intel specific assembly language?

> You'll need to turn optimisations on everywhere though.
Jon Skeet [C# MVP] - 20 Nov 2006 17:51 GMT
> > Compile a simple test app, run it under cordbg, and look at the
> > assembly generated.
>
> Is it possible to look at the actual Intel specific assembly language?

Absolutely. It's not the easiest tool to get the hang of, but it's not
too bad after a bit of playing.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Arne Vajhøj - 18 Nov 2006 21:22 GMT
> Can  allocating an ordinary array, be done through the managed heap? If it can
> not be done using the managed heap, then wouldn't allocating unmanaged memory be
> considered a poor practice in terms of good .NET design?

A normal array in C# is in managed heap.

And there are nothing wrong with using normal arrays in C#
if you know the size.

Arne
Peter Olcott - 18 Nov 2006 02:36 GMT
>> So then the answer is clear, .NET without generics can be unacceptably slow,
>> 58-fold slower than unmanaged array storage and 500% slower than unmanaged
[quoted text clipped - 7 lines]
>
> Arne

Oh Yeah, one more question, an Array List can be allocated in advance, can't it?
Arne Vajhøj - 18 Nov 2006 15:27 GMT
> Oh Yeah, one more question, an Array List can be allocated in advance, can't it?

Both ArrayList and List<> has a constructor with an int argument
specifying initial capacity.

Arne
Peter Olcott - 18 Nov 2006 17:13 GMT
>> Oh Yeah, one more question, an Array List can be allocated in advance, can't
>> it?
[quoted text clipped - 3 lines]
>
> Arne

These can refer to any type of structure?
Which of these is closest to std::vector?
Arne Vajhøj - 18 Nov 2006 21:20 GMT
>>> Oh Yeah, one more question, an Array List can be allocated in advance, can't
>>> it?
[quoted text clipped - 3 lines]
> These can refer to any type of structure?
> Which of these is closest to std::vector?

ArrayList uses object meaning that it can take anything
but do boxing and unboxing.

List<> uses whatever you use including struct (that is how
generics work).

Arne
Jeff Louie - 19 Nov 2006 03:09 GMT
Just to be clear, I believe std::vector is finally available in C++/CLI.

Regards,
Jeff
Arne Vajhøj - 23 Nov 2006 21:52 GMT
> Just to be clear, I believe std::vector is finally available in C++/CLI.

When has it not been ?

It seems to work (for a very simple example) in both
7.1/2003 and 8.0/2005.

Arne
Jeff Louie - 24 Nov 2006 06:30 GMT
Arne... Managed STL aka STL.NET was a delayed release after the RTM of
Visual
Studio 2005.

http://msdn2.microsoft.com/en-us/library/ms379600(vs.80).aspx

Regards,
Jeff
Jeff Louie wrote:
> Just to be clear, I believe std::vector is finally available in C++/CLI.

When has it not been ?

It seems to work (for a very simple example) in both
7.1/2003 and 8.0/2005.
Willy Denoyette [MVP] - 24 Nov 2006 10:00 GMT
> Arne... Managed STL aka STL.NET was a delayed release after the RTM of
> Visual
> Studio 2005.
>
> http://msdn2.microsoft.com/en-us/library/ms379600(vs.80).aspx

But, std::vector is a STL container, not a managed STL (now officially named STL/CLR)
container, and these were available since VC6.
Note that STL/CLR is now scheduled for ORCAS.

Willy.
Peter Olcott - 24 Nov 2006 13:19 GMT
>> Arne... Managed STL aka STL.NET was a delayed release after the RTM of
>> Visual
[quoted text clipped - 5 lines]
> STL/CLR) container, and these were available since VC6.
> Note that STL/CLR is now scheduled for ORCAS.

It is scheduled for killer whales?

> Willy.
Jeff Louie - 24 Nov 2006 20:15 GMT
Willy... I must very dense. I thought the OP was trying to write in
managed code
using patterns that he was familiar with such as the STL. I was trying
to point
out that his knowledge base in STL is still valuable and that this
knowledge can
be utilized in writing managed code if uses managed STL.

Regards,
Jeff
>But, std::vector is a STL container, not a managed STL (now officially named
STL/CLR) container, and these were available since VC6.<
Peter Olcott - 24 Nov 2006 20:39 GMT
> Willy... I must very dense. I thought the OP was trying to write in
> managed code
[quoted text clipped - 3 lines]
> knowledge can
> be utilized in writing managed code if uses managed STL.

That info was very useful too, thanks. I might do it that way with STL.

> Regards,
> Jeff
[quoted text clipped - 3 lines]
>
> *** Sent via Developersdex http://www.developersdex.com ***
Willy Denoyette [MVP] - 24 Nov 2006 21:51 GMT
> Willy... I must very dense. I thought the OP was trying to write in
> managed code
[quoted text clipped - 11 lines]
>
> *** Sent via Developersdex http://www.developersdex.com ***

Jeff,
I don't see a reason to be dense, in your reply  to  Arne:
> Just to be clear, I believe std::vector is finally available in
C++/CLI.

I noticed the "finally", and that's why I said that std:vector is a native STL container,
which is available in all versions of VC++ since VC6. Don't know why you did use *finally*
here, really.

Willy.
Jeff Louie - 25 Nov 2006 00:12 GMT
Huh. OK. You are right. I am wrong.

Regards,
Jeff
Peter Olcott - 24 Nov 2006 13:21 GMT
I would suppose that managed STL is not directly available from C#, and only
available from C++, right?

> Arne... Managed STL aka STL.NET was a delayed release after the RTM of
> Visual
[quoted text clipped - 14 lines]
>
> *** Sent via Developersdex http://www.developersdex.com ***
Willy Denoyette [MVP] - 24 Nov 2006 17:01 GMT
>I would suppose that managed STL is not directly available from C#, and only available from
>C++, right?

The primary target is C++/CLI, but the STL/CLR containers can be operated on from any
managed language, like this:.

public ref class DataEngine {
public: ...
        System::Collections::Generic::ICollection<int>^ GetDataContainer()
        {
           return m_data;
       }
private:
        cliext::vector<int>^ m_data;  // a STL/CLR vector
};

//C# consumer
      ...
       m_DataEng = new DataEngine();
       ICollection<int> iColl = m_DataEng.GetDataContainer();
            foreach (Object objCur in iColl)
            { ... }

Willy.
Jon Skeet [C# MVP] - 05 Nov 2006 08:09 GMT
> That would make it infeasible. Generics completely bypass boxing and unboxing,
> right?

Assuming you mean using List<int> instead of ArrayList, etc, then yes.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Peter Olcott - 05 Nov 2006 13:52 GMT
>> That would make it infeasible. Generics completely bypass boxing and
>> unboxing,
>> right?
>
> Assuming you mean using List<int> instead of ArrayList, etc, then yes.

I need the C# equivalent of std::vector. It must be able to dynamically grow in
size, and it must not have any more overhead than an unmanaged array of struct.
Jon Skeet [C# MVP] - 05 Nov 2006 14:24 GMT
> > Assuming you mean using List<int> instead of ArrayList, etc, then yes.
>
> I need the C# equivalent of std::vector. It must be able to dynamically grow in
> size, and it must not have any more overhead than an unmanaged array of struct.

Well, there will be a *slight* overhead when it comes to accessing
(because it'll need to check the size against the size of the list as
well as then against the size of the backing array) but yes, List<T> is
basically what you want.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Arne Vajhøj - 05 Nov 2006 18:24 GMT
> "Arne Vajhøj" <arne@vajhoej.dk> wrote in message
>> integer array: 0,046875
[quoted text clipped - 8 lines]
>> is the acceptable, then you can box and unbox 7000 times in
>> your code.