Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does boxing create garbage in .NET?

I'm wondering whether boxing a value type in an object is a special case or whether the "box" constructed by .NET becomes garbage (that the GC has to collect) after any references to it are dropped.

For example, StringBuilder.AppendFormat() has these overloads:

StringBuilder.AppendFormat(string format, object arg0);
StringBuilder.AppendFormat(string format, object arg0, object arg1);
StringBuilder.AppendFormat(string format, object arg0, object arg1, object arg2);
StringBuilder.AppendFormat(string format, params object[] args);

Having those additional overloads for calls with 3 or fewer arguments might indicate that boxing indeed is a special case (or that it pays off, from a performance point-of-view, to avoid array construction).

Theoretically, using plain old reference counting, possibly with a pool of reusable boxes would be a valid implementation because there can be no references from one box to another, only from .NET objects to a box.

like image 277
Cygon Avatar asked Feb 09 '10 06:02

Cygon


People also ask

Can garbage collection be forced in net?

GC. Collect() Method : Garbage collection can be forced in the system using the GC. Collect() method.

What is consequence of boxing and unboxing?

Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the common language runtime (CLR) boxes a value type, it wraps the value inside a System. Object instance and stores it on the managed heap. Unboxing extracts the value type from the object.

How performance is affected due to boxing and unboxing?

During process of boxing and unboxing, it may be possible that the performance of conversion is being affected due the large number of items stored in a collection. I've done a bit of research over this and here is my conclusion. As a general conclusion, we can say that an object is equivalent to a 'void *' of c++.

How can we avoid boxing and unboxing?

How to prevent boxing & unboxing: Use ToString method of numeric data types such as int, double, float etc. Use for loop to enumerate on value type arrays or lists (do not use foreach loop or LINQ queries) Use for loop to enumerate on characters of string (do not use foreach loop or LINQ queries)


2 Answers

First off, just to clarify: creating an array of object references is not boxing. "Boxing" is a term with a very specific meaning in .NET, and I think it's worth sticking to it.

Boxing does create garbage - or rather, each time you box, it creates a new object which is likely to eventually become garbage. (It doesn't have to become garbage - you might have a reference to that object for the rest of the app's lifetime; it's just pretty rare.)

However, you could have a cache for boxing purposes. Indeed, Java does for small numbers. If you write:

Integer x = 5;
Integer y = 5;
System.out.println(x == y); // Reference comparison

then that's guaranteed to print true.

However, that's just a small cache for a fixed set of types - it's not a general purpose cache. You need to balance the pain of having a general cache with weak references (not reference counting - the GC mechanism in .NET just isn't reference counted, and you couldn't really introduce that just for boxed values) would almost certainly hurt performance more than the small cost of boxing creating garbage.

.NET could have taken the same approach as Java and boxed some values of some types, but I'm not sure it's worth the extra conceptual baggage - especially when the platform supports custom value types (which Java doesn't).

It's probably worth noting that since .NET 2.0, boxing is somewhat rarer than it used to be. It happens a fair amount in data binding and reflection, but it's less common in plain old data manipulation now.

like image 62
Jon Skeet Avatar answered Oct 29 '22 15:10

Jon Skeet


A value type that is boxed becomes an object on the heap, and like any other object must (and will) be garbage collected once it is no longer referenced.

Creating method overloads with 3 or fewer arguments is (as you observe) to avoid array construction, and is a performance optimization. See "Consider providing special overloads and code paths for calls with a small number of arguments in extremely performance-sensitive APIs" at Members with a Variable Number of Parameters.

However, creating an array is fundamentally different than boxing a value type. Calling any overload of StringBuilder.AppendFormat will always box arguments that are value types, because the parameter is typed as object, whether or not an array is created. For a detailed explanation of boxing, see "Boxing and Unboxing" at .NET: Type Fundamentals.

like image 3
Bradley Grainger Avatar answered Oct 29 '22 15:10

Bradley Grainger