2010-02-09 6 views
5

Me pregunto si encajonar un tipo de valor en un objeto es un caso especial o si el "cuadro" construido por .NET se convierte en basura (que el GC tiene que recopilar) después de que se omitan las referencias a él.¿El boxeo crea basura en .NET?

Por ejemplo, StringBuilder.AppendFormat() tiene estas sobrecargas:

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); 

Tener esas sobrecargas adicionales para llamadas con 3 o menos argumentos podría indicar que el boxeo de hecho es un caso especial (o que vale la pena, desde un punto de vista de rendimiento, para evitar la construcción de matriz).

Teóricamente, usar el recuento de referencias antiguo simple, posiblemente con un grupo de cajas reutilizables sería una implementación válida porque no puede haber referencias de una caja a otra, solo de objetos .NET a una caja.

Respuesta

8

En primer lugar, solo para aclarar: crear una matriz de referencias de objetos es no boxeo. "Boxeo" es un término con un significado muy específico en .NET, y creo que vale la pena seguirlo.

boxing crear basura - o mejor dicho, cada vez que la caja, crea un nuevo objeto que con el tiempo se convertirá en basura. (No han para convertirse en basura - es posible que tenga una referencia a ese objeto para el resto de la vida de la aplicación, es sólo muy rara.)

Sin embargo, podría tener un caché para los propósitos de boxeo . De hecho, Java lo hace por números pequeños. Si se escribe:

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

continuación, que está garantizado para imprimir true.

Sin embargo, eso es solo un pequeño caché para un conjunto fijo de tipos; no es un caché de propósito general. Necesita equilibrar el dolor de tener un caché general con referencias débiles (no cuenta de referencias; el mecanismo del GC en .NET solo no es referencia contada, y realmente no se podía introducir ese solo para los valores encuadrados) casi seguramente perjudica el rendimiento más que el pequeño costo del boxeo creando basura.

.NET podría tener tiene el mismo enfoque que Java y recuadro algunos valores de algunos tipos, pero no estoy seguro de que valga la pena el bagaje conceptual adicional, especialmente cuando la plataforma admite tipos de valores personalizados (que Java no)

Es probable que valga la pena señalar que desde .NET 2.0, el boxeo es algo más raro de lo que solía ser. Ocurre una buena cantidad en el enlace de datos y la reflexión, pero ahora es menos común en la antigua manipulación de datos.

+0

Me estoy apegando al significado específico de "boxeo" en .NET. Me preguntaba si esas sobrecargas en la clase StringBuilder solo estaban ahí para evitar * basura * adicional en la forma de la matriz, o si evitarían * toda * basura porque, por ejemplo. encajonar un entero en un objeto no produciría basura. – Cygon

+0

@Cygon: Creo que traer la creación de matriz automática con un parámetro "params" oscureció algo su pregunta: las sobrecargas son completamente irrelevantes para el boxeo. Sí, las sobrecargas podrían evitar crear basura adicional, aunque no creo que lo hagan. Creo que las sobrecargas de los parámetros individuales realmente llaman a uno con una matriz, creando la matriz de forma explícita. Sin embargo, ayuda a los lenguajes que no admiten matrices de parámetros. –

+0

No creo que su código Java * esté garantizado * para imprimir 'true'. * Imprimirá "verdadero" con la JVM de Sun, porque la implementación de 'Integer.valueOf (int)' (el método utilizado internamente para el boxeo) almacena en caché instancias 'Integer' para valores de -128 a 127, pero eso no es una * requisito * de la plataforma Java. Otra JVM podría reclamar la conformidad sin dicho almacenamiento en caché. –

3

Un tipo de valor que está encuadrado se convierte en un objeto en el montón, y como cualquier otro objeto debe (y será) recolectado como basura una vez que ya no se hace referencia.

La creación de sobrecargas de métodos con 3 o menos argumentos es (como se observa) para evitar la construcción de matrices, y es una optimización del rendimiento. Consulte "Considere proporcionar sobrecargas especiales y rutas de código para llamadas con una pequeña cantidad de argumentos en API extremadamente sensibles al rendimiento" al Members with a Variable Number of Parameters.

Sin embargo, crear una matriz es fundamentalmente diferente de boxear un tipo de valor. Llamar a cualquier sobrecarga de StringBuilder.AppendFormat siempre encajonará argumentos que sean tipos de valores, porque el parámetro se escribe como object, independientemente de si se creó una matriz. Para una explicación detallada del boxeo, ver "Boxeo y Unboxing" en .NET: Type Fundamentals.

0

Usted está haciendo la pregunta incorrecta.

Las sobrecargas que está apuntando a optimizar para la llamada directa de parámetros. Lo que significa que el compilador colocará las variables en arg_0, arg_1, arg_2, arg_3, es posible tener más que eso, pero el IL solo las tiene como acceso rápido. El resto pasa por la pila de todos modos, y por lo tanto no es mucho más eficiente que la llamada de función de tipo param.

Para la llamada a la función de tipo param, en realidad hace una matriz detrás de los scenenes y la envía a la función como arg_1 (en este caso, donde arg_0 es captada por la cadena).

+0

Lo siento, no. Sé todo eso (sí, hasta el nivel de convenciones de llamadas) y creo que mi pregunta muestra que * no * estoy preguntando sobre el sentido de las sobrecargas de StringBuilder. He citado al StringBuilder como una posible indicación de que el boxeo podría evitar la basura (sobre la base de que evitar la matriz * podría * no solo ser por motivos de rendimiento sino también para reducir la basura innecesaria) – Cygon

Cuestiones relacionadas