473,890 Members | 1,930 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

What would be a faster alternative to boxing/unboxing?

I have a situation where an app writes data of various types (primitives and
objects) into a single dimensional array of objects. (This array eventually
becomes a row in a data table, but that's another story.) The data is
written once and then read many times. Each primitive read requires
unboxing. The data reads are critical to overall app performance. In the
hopes of improving performance, we have tried to find a way to avoid the
unboxing and casting. So far, nothing has worked well.

One solution we tried was to create our own simple object to wrap the
primitives. In this object we used a public field that allowed reading of
the primitive data value without a property or unboxing. However, overall
performance went down. We are still investigating, but our current
speculations are that:
1. the overhead of creating the object was significantly greater than the
overhead of boxing and this offset any gains we might have gotten on the
reads (a guess).
2. wrapping each primitive forced us to introduce a new virtual method call
in place of the boxing/casting. Maybe the overhead of this call is what
caused the performance to go down. (Another guess.)

BTW, performance went down 15%.

Does anyone have any ideas on how to implement the following:

A 1-dimension array (with normal indexing) containing heterogenous strongly
typed data that allows reading/writing without casting and without
boxing/unboxing.

All thoughts/suggestions are appreciated.


Nov 15 '05
43 6926
Hi Eric,
You can certainly call me Mountain ;) I have a small mountain bike track
outside my back door (it's more like a BMX track). About the only time I
leave the computer is when I go ride my mountain bike (or when my wife
forces me to go to sleep).

Thanks for your input and the link to the CLR profiler. I think using the
CLR profiler is a good next step.
Regards,
Dave

"Eric Gunnerson [MS]" <er****@online. microsoft.com> wrote in message
news:uN******** ******@tk2msftn gp13.phx.gbl...
Mountain (can I call you Mountain...),

The overhead from boxing should be roughly equivalent to the overhead of
creating the wrapper class, as they're doing nearly exactly the same thing. I'm not sure how to contrast the overhead of the two options in #2 - my
guess is that virtual dispatch is roughly as expensive as an unbox, but if
you do the virtual every time and the unbox only on value types, it could
explain your results.

You should also probably spend some time using the CLR profiler to examine
your application.

http://www.microsoft.com/downloads/d...displaylang=en

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights. "Mountain Bikn' Guy" <vc@attbi.com > wrote in message
news:_W6vb.1969 14$9E1.1057145@ attbi_s52...
I have a situation where an app writes data of various types (primitives

and
objects) into a single dimensional array of objects. (This array

eventually
becomes a row in a data table, but that's another story.) The data is
written once and then read many times. Each primitive read requires
unboxing. The data reads are critical to overall app performance. In the
hopes of improving performance, we have tried to find a way to avoid the
unboxing and casting. So far, nothing has worked well.

One solution we tried was to create our own simple object to wrap the
primitives. In this object we used a public field that allowed reading of the primitive data value without a property or unboxing. However, overall performance went down. We are still investigating, but our current
speculations are that:
1. the overhead of creating the object was significantly greater than the overhead of boxing and this offset any gains we might have gotten on the
reads (a guess).
2. wrapping each primitive forced us to introduce a new virtual method

call
in place of the boxing/casting. Maybe the overhead of this call is what
caused the performance to go down. (Another guess.)

BTW, performance went down 15%.

Does anyone have any ideas on how to implement the following:

A 1-dimension array (with normal indexing) containing heterogenous

strongly
typed data that allows reading/writing without casting and without
boxing/unboxing.

All thoughts/suggestions are appreciated.


Nov 15 '05 #11
100 wrote:
Hi Paul,
Have to excuse me as I'm new to C# :)

My understanding is you can't have an array of objects with value types
without boxing. As the instant you do obArray[x] = 32 it boxes it.


Not quite true.
If you have

struct MyStruct
{
.....
}

MyStruct [] arr = new MyStruct[XXX];
arr[0] = new MyStruct() ; //that won't cause any boxing.
MyStruct ms = arr[0]; //won't cause any unboxing because nothing has been
boxed

Anyway, it might not cause boxing, but the value will be copied which will
introduce some overhead compared to the case if we use reference type
instead of value type.


Hm. So structs are this sort of wierd interim type between values and
objects ? I find the whole thing not confusing but maybe inconsistent.

If you can assign a struct to an object reference what happens if you have

sometype somefunc(object[] a)
{
a[1] = new MyStruct()
}

My understanding is that MyStruct[] is allocated off the stack not the
heap. So when the stack frame is removed, what does a[1] point to ?

It doesn't seem very "safe" - unless it does a struct copy (as in
struct1=struct2 ) and allocates that on the heap ?

Sorry if these are dumb questions :) I only started C# a couple of days ago.
Nov 15 '05 #12
100 wrote:
class Storage
{
int[] intArr= new int[10];
double[] dblArr = new int[10];
object[] refArr = new object[10];

public int this[int i]
{
get{return intArr[i];}
set{intArr[i] = value;}
}

public double this[int i]


I thought that C# couldn't do polymorphism on return types only ? Am I
wrong ?

Nov 15 '05 #13
100
Hi Paul,

No, the question is not dumb at all.
Hm. So structs are this sort of wierd interim type between values and
objects ? I find the whole thing not confusing but maybe inconsistent.
No, the struct are value types. If you look at the docs value types are:
primitives (int32, int64, char, etc), enums and structures. So take a look
at MSDN. Int32 for example is decalred as a *struct*. They are called
primitives because IL has special instructions to work with them directly.
That is why you won't see any overloads of the arithmetic operators defined
for them. Decimal, though, is not a primitive so it has overloaded the
arithmetic operators and this is the reason why the performance is worse
when you work with them compared with double for example.

If you can assign a struct to an object reference what happens if you have

sometype somefunc(object[] a)
{
a[1] = new MyStruct()
}

My understanding is that MyStruct[] is allocated off the stack not the
heap. So when the stack frame is removed, what does a[1] point to ?

It doesn't seem very "safe" - unless it does a struct copy (as in
struct1=struct2 ) and allocates that on the heap ?

Sorry if these are dumb questions :) I only started C# a couple of days ago.
Value types may be in two states: boxed and unboxed, how you know. When they
are in boxed state they are always in the managed heap. When they are in
unboxed state they might be in the heap or in the stack. In c# we can have
unboxed value type in the heap only when they are part of the reference
object (which is allocated always in the heap). I said in C# because for
CLR's point of view the operation of unboxing doesn't do the copy of the
value type from the heap to the stack. You might have boxed value type in
the heap and then doing *unbox* it gets a pointer to the data part of the
object (pointer to the unboxed object) and pushed it in the evaluation
stack. It doesn't copy the data from the heap. However, because in most of
the cases the opertation of unboxing is followed by operatation of copying
the data C# designers desided not to provide unboxing in the heap. In C#
unboxing is always followed by copy. You can do it in VC++ or ILAsm, though.

So arrays are reference types. As reference types they reside in the heap.
But if they are of type *value type* the items are in unboxed state in the
heap as if they were data members of a class.
So, if you have

int[] intArr = new int[10];
intArr[0] = 10;
the value type 10 won't be boxed in the array it will be copied in the heap
in unboxed state.

What happens here sometype somefunc(object[] a)
{
a[1] = new MyStruct()
}


new MyStruct will create indeed the strucutre in the stack. But then the
assignment will copy this value form the stack to the heap. The original one
which is in the stack will go away when the stack frame gets removed but its
verbatim copy in the heap will stay as part of the array.

HTH
B\rgds
100
Nov 15 '05 #14
100
Hi Paul,
You are hundred percent right. That was my fault. I wrote this minutes
before I went home yesterday and its my fault that I posted this without any
revision.

Thanks for bringing this out. We can't use indexer for that. What we can do
is to use separate operations SetData and GetData with as many overloads as
different types we want to accept. GetData cannot return value because ot
will introduce the same problem that we have already with the indexer. So we
can have prototype like

void GetData(int index, out <type> value)
{
}

this should fix the problem.

B\rgds
100

"Paul Robson" <au******@autis muk.muralichuck s.freeserve.co. uk> wrote in
message news:bp******** **@news8.svr.po l.co.uk...
100 wrote:
class Storage
{
int[] intArr= new int[10];
double[] dblArr = new int[10];
object[] refArr = new object[10];

public int this[int i]
{
get{return intArr[i];}
set{intArr[i] = value;}
}

public double this[int i]


I thought that C# couldn't do polymorphism on return types only ? Am I
wrong ?

Nov 15 '05 #15
100 wrote:
What happens here
sometype somefunc(object[] a)
{
a[1] = new MyStruct()
}

new MyStruct will create indeed the strucutre in the stack. But then the
assignment will copy this value form the stack to the heap. The original one
which is in the stack will go away when the stack frame gets removed but its
verbatim copy in the heap will stay as part of the array.

HTH
B\rgds
100


Thanks ! It's much clearer now :)

Nov 15 '05 #16
100
The real problem with this idea is - how we can possibly know which type is
the object at given index in order to know what overload to use to retrieve
the data. We can provide method that returns the type of an object by index
value. But then we need to check this type and call the appropriate method
which will introduce more overhead when reading data. It may turns that
boxing/unboxing is the best solution and the problem with the prformance is
not there.

That's why I think we can't come up with good idea unless Mountain gives us
an example how he is planning to use this storage. He may not need to have
the objects ordered and then this solution will work and we won't have the
problem of wasting the memory.

B\rgds
100

"100" <10*@100.com> wrote in message
news:eb******** ********@TK2MSF TNGP09.phx.gbl. ..
Hi Paul,
You are hundred percent right. That was my fault. I wrote this minutes
before I went home yesterday and its my fault that I posted this without any revision.

Thanks for bringing this out. We can't use indexer for that. What we can do is to use separate operations SetData and GetData with as many overloads as different types we want to accept. GetData cannot return value because ot
will introduce the same problem that we have already with the indexer. So we can have prototype like

void GetData(int index, out <type> value)
{
}

this should fix the problem.

B\rgds
100

"Paul Robson" <au******@autis muk.muralichuck s.freeserve.co. uk> wrote in
message news:bp******** **@news8.svr.po l.co.uk...
100 wrote:
class Storage
{
int[] intArr= new int[10];
double[] dblArr = new int[10];
object[] refArr = new object[10];

public int this[int i]
{
get{return intArr[i];}
set{intArr[i] = value;}
}

public double this[int i]


I thought that C# couldn't do polymorphism on return types only ? Am I
wrong ?


Nov 15 '05 #17
Well, it is just a guess, but here's my reasoning.

The virtual dispatch by itself isn't a big deal - it's only an extra few
instructions. But because it's virtual (and there could be derived classes
loaded later), the JIT doesn't inline virtual calls, so you do pay a
non-trivial penalty there.

Unbox, on the other hand, is a runtime type check (fairly cheap), and then a
copy of memory from the reference location to the stack location. That's
pretty cheap, and my guess is that it's cheaper than the lost inline

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
"100" <10*@100.com> wrote in message
news:%2******** *********@TK2MS FTNGP11.phx.gbl ...
Hi Eric,

I agree that using wrapping classes is probably as slow (even it could be
slower) than boxing/unboxing. And I gave my point in my prevoius post.
However I'm not qiute sure what you are saying here
guess is that virtual dispatch is roughly as expensive as an unbox


In .NET dispatching of virtual-method calls is pretty simple and doesn't
take much work than the calls of non-virtual methods. So if what you are
saying is true it means that every function calls is as expensive as unbox
operation.

B\rgds
100

You should also probably spend some time using the CLR profiler to examine
your application.

http://www.microsoft.com/downloads/d...displaylang=en


--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no

rights.
"Mountain Bikn' Guy" <vc@attbi.com > wrote in message
news:_W6vb.1969 14$9E1.1057145@ attbi_s52...
I have a situation where an app writes data of various types (primitives
and
objects) into a single dimensional array of objects. (This array

eventually
becomes a row in a data table, but that's another story.) The data is
written once and then read many times. Each primitive read requires
unboxing. The data reads are critical to overall app performance. In

the hopes of improving performance, we have tried to find a way to avoid the unboxing and casting. So far, nothing has worked well.

One solution we tried was to create our own simple object to wrap the
primitives. In this object we used a public field that allowed reading

of the primitive data value without a property or unboxing. However, overall performance went down. We are still investigating, but our current
speculations are that:
1. the overhead of creating the object was significantly greater than the overhead of boxing and this offset any gains we might have gotten on the reads (a guess).
2. wrapping each primitive forced us to introduce a new virtual method

call
in place of the boxing/casting. Maybe the overhead of this call is what caused the performance to go down. (Another guess.)

BTW, performance went down 15%.

Does anyone have any ideas on how to implement the following:

A 1-dimension array (with normal indexing) containing heterogenous

strongly
typed data that allows reading/writing without casting and without
boxing/unboxing.

All thoughts/suggestions are appreciated.



Nov 15 '05 #18
100
Hi Eric,
Well, it is just a guess, but here's my reasoning.

The virtual dispatch by itself isn't a big deal - it's only an extra few
instructions. But because it's virtual (and there could be derived classes
loaded later), the JIT doesn't inline virtual calls, so you do pay a
non-trivial penalty there.

Unbox, on the other hand, is a runtime type check (fairly cheap), and then a copy of memory from the reference location to the stack location. That's
pretty cheap, and my guess is that it's cheaper than the lost inline
Pretty wild guess I think ;)

1. There is no guarantee that a non-virtual method will be inlined.

2. Unboxing is a cheep operation. The copy operation which c# generates
always after unboxing could be expensive depending on the size of the value
type data. Calling virtual function is like indirect call with two
indirections and if the method doesn't have any parameters (which have to be
copied in the stack) - like simple GetMethod - I don't think it would be
more expensive then unboxing (event if it does have paramters if they are
primitives or reference types the fist two will be transfered via CPU
registeres, the return value as well could be passed back thru
register(s) ).

Of course this guess is as wild as yours ;)
B\rgds
100

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights. "100" <10*@100.com> wrote in message
news:%2******** *********@TK2MS FTNGP11.phx.gbl ...
Hi Eric,

I agree that using wrapping classes is probably as slow (even it could be
slower) than boxing/unboxing. And I gave my point in my prevoius post.
However I'm not qiute sure what you are saying here
guess is that virtual dispatch is roughly as expensive as an unbox


In .NET dispatching of virtual-method calls is pretty simple and doesn't
take much work than the calls of non-virtual methods. So if what you are
saying is true it means that every function calls is as expensive as unbox operation.

B\rgds
100

You should also probably spend some time using the CLR profiler to examine your application.

http://www.microsoft.com/downloads/d...displaylang=en


--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no

rights.
"Mountain Bikn' Guy" <vc@attbi.com > wrote in message
news:_W6vb.1969 14$9E1.1057145@ attbi_s52...
> I have a situation where an app writes data of various types (primitives and
> objects) into a single dimensional array of objects. (This array
eventually
> becomes a row in a data table, but that's another story.) The data is > written once and then read many times. Each primitive read requires
> unboxing. The data reads are critical to overall app performance. In the > hopes of improving performance, we have tried to find a way to avoid the > unboxing and casting. So far, nothing has worked well.
>
> One solution we tried was to create our own simple object to wrap the > primitives. In this object we used a public field that allowed reading of
> the primitive data value without a property or unboxing. However,

overall
> performance went down. We are still investigating, but our current
> speculations are that:
> 1. the overhead of creating the object was significantly greater
than
the
> overhead of boxing and this offset any gains we might have gotten on

the > reads (a guess).
> 2. wrapping each primitive forced us to introduce a new virtual meth
od call
> in place of the boxing/casting. Maybe the overhead of this call is

what > caused the performance to go down. (Another guess.)
>
> BTW, performance went down 15%.
>
> Does anyone have any ideas on how to implement the following:
>
> A 1-dimension array (with normal indexing) containing heterogenous
strongly
> typed data that allows reading/writing without casting and without
> boxing/unboxing.
>
> All thoughts/suggestions are appreciated.
>
>
>
>



Nov 15 '05 #19
Here's the answer to your question (I hope):

The ordering is determined by computational dependencies. Just before
processing starts, an ordering is determined dynamically. Then during
processing, items are written to the array in that order. There is actually
an external index that is used to find items in the array.

Does that answer your question?

I do currently use 'out' parameters in the overloaded methods that retreive
data from the array, as you figured out.

I've written code for other approaches too. I have lots of alternative
implementations that I have tested. As a side note -- which isn't really
relevant to the main topic -- when I need to have overloaded return types, I
use this approach:

<type> GetData(int index, <type> value)
{
return (type)valueList[index];//cast to <type>
}

What this does is use a parameter to chose an overload, and each overload
has a different return type. It is very similar to the 'out' approach except
the data is returned in a more familiar way.

I hope mentioning this doesn't divert this thread from the main topic. My
concern is still more with a design that might solve the problem more
creatively. I have an interesting approach that I tested a couple days ago.
I'll post some example code this weekend.

Thanks for your interest in the topic!
Mountain

"100" <10*@100.com> wrote in message
news:eQ******** ******@TK2MSFTN GP10.phx.gbl...
The real problem with this idea is - how we can possibly know which type is the object at given index in order to know what overload to use to retrieve the data. We can provide method that returns the type of an object by index value. But then we need to check this type and call the appropriate method
which will introduce more overhead when reading data. It may turns that
boxing/unboxing is the best solution and the problem with the prformance is not there.

That's why I think we can't come up with good idea unless Mountain gives us an example how he is planning to use this storage. He may not need to have
the objects ordered and then this solution will work and we won't have the
problem of wasting the memory.

B\rgds
100

"100" <10*@100.com> wrote in message
news:eb******** ********@TK2MSF TNGP09.phx.gbl. ..
Hi Paul,
You are hundred percent right. That was my fault. I wrote this minutes
before I went home yesterday and its my fault that I posted this without any
revision.

Thanks for bringing this out. We can't use indexer for that. What we can

do
is to use separate operations SetData and GetData with as many overloads

as
different types we want to accept. GetData cannot return value because ot will introduce the same problem that we have already with the indexer.

So we
can have prototype like

void GetData(int index, out <type> value)
{
}

this should fix the problem.

B\rgds
100

"Paul Robson" <au******@autis muk.muralichuck s.freeserve.co. uk> wrote in
message news:bp******** **@news8.svr.po l.co.uk...
100 wrote:

> class Storage
> {
> int[] intArr= new int[10];
> double[] dblArr = new int[10];
> object[] refArr = new object[10];
>
> public int this[int i]
> {
> get{return intArr[i];}
> set{intArr[i] = value;}
> }
>
> public double this[int i]

I thought that C# couldn't do polymorphism on return types only ? Am I
wrong ?



Nov 15 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
2650
by: ALI-R | last post by:
Hi All, First of all I think this is gonna be one of those threads :-) since I have bunch of questions which make this very controversial:-0) Ok,Let's see: I was reading an article that When you pass a Value-Type to method call ,Boxing and Unboxing would happen,Consider the following snippet: int a=1355; myMethod(a); ......
94
5729
by: Peter Olcott | last post by:
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.
161
7914
by: Peter Olcott | last post by:
According to Troelsen in "C# and the .NET Platform" "Boxing can be formally defined as the process of explicitly converting a value type into a corresponding reference type." I think that my biggest problem with this process is that the terms "value type" and "reference type" mean something entirely different than what they mean on every other platform in every other language. Normally a value type is the actual data itself stored in...
29
2360
by: calvert4rent | last post by:
I need to some sort of data type that will hold a listing of ID's and their counts/frequency. As I do some processing I get an ID back which I need to store and keep an accurate count for how many times that ID is listed. For example I might get a listing of these numbers: 1,4,6,23,6,2,54,1,6,23,2,4,1,6 I will get those numbers one at a time and need to build something like 1,3
0
9814
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11214
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10801
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
10449
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
8006
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7158
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5834
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4659
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3266
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.