ArrayList without Boxing and UnBoxing

P

Peter Olcott

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.
 
M

Mythran

Peter Olcott said:
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
 
B

Bruce Wood

Peter said:
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.
 
B

Bill Rodenbaugh

B

Bruce Wood

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.
 
P

Peter Olcott

Bruce Wood said:
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.

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.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Peter said:
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.

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

Arne
 
B

Bruce Wood

Peter said:
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.

Is there a particular reason why you're porting to .NET 1.1? .NET 2.0
is far better.
 
P

Peter Olcott

Arne Vajhøj said:
You can box and unbox a lot of variables before it is noticeable in
1/10 second time intervals.

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.
 
M

Mark Wilden

Peter Olcott said:
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
 
P

Peter Olcott

Mark Wilden said:
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

How many clock cycles does one unboxing operation take?
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

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;
}
for(int i = 0; i < N; i++)
{
if(ia != 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;
}
for(int i = 0; i < N; i++)
{
if((int)oa != i)
{
Console.WriteLine("Oops");
Environment.Exit(1);
}
}
DateTime dt4 = DateTime.Now;
Console.WriteLine("object array: " + (dt4 - dt3).TotalSeconds);
Console.ReadKey();
}
}
}
 
P

Peter Olcott

That would make it infeasible. Generics completely bypass boxing and unboxing,
right?

Arne Vajhøj said:
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;
}
for(int i = 0; i < N; i++)
{
if(ia != 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;
}
for(int i = 0; i < N; i++)
{
if((int)oa != i)
{
Console.WriteLine("Oops");
Environment.Exit(1);
}
}
DateTime dt4 = DateTime.Now;
Console.WriteLine("object array: " + (dt4 - dt3).TotalSeconds);
Console.ReadKey();
}
}
}
 
B

Bruce Wood

Peter said:
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.
 
J

Jon Skeet [C# MVP]

Peter Olcott said:
That would make it infeasible. Generics completely bypass boxing and unboxing,
right?

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

Peter Olcott

Jon Skeet said:
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.
 
P

Peter Olcott

Bruce Wood said:
Yes. Generics allow the compiler to create aggregate structures that
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?
 
J

Jon Skeet [C# MVP]

Peter Olcott said:
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.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

That would make it infeasible. Generics completely bypass boxing and unboxing,
right?

You need to do more than 7000 boxing and unboxing every 1/10 seconds
with less overhead than 1/100 ?

I would call that rather unusual requirements.

Yes - generics will avoid boxing and unboxing, but it will
add some overhead too.

Arne
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Peter said:
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
 

Ask a Question

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

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

Ask a Question

Top