.NET Forum / Languages / C# / November 2006
ArrayList without Boxing and UnBoxing
|
|
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. |
|