¿La agrupación de objetos es una técnica obsoleta?

62

Estoy muy familiarizado con el concepto de agrupación de objetos y siempre trato de usarlo tanto como sea posible.

Además, siempre pensé que la agrupación de objetos es la norma estándar, ya que he observado que tanto Java como los otros marcos usan la agrupación tanto como sea posible.

Recientemente, aunque leí algo que era completamente nuevo (¿y contra intuitivo?) Para mí.

Esa agrupación en realidad empeora el rendimiento del programa, especialmente en aplicaciones concurrentes, y es aconsejable instanciar newobjetos en su lugar, ya que en las JVM más nuevas, la creación de instancias de un objeto es realmente rápida.

Leí esto en el libro: Java Concurrency in Practice

Ahora estoy empezando a pensar si estoy entendiendo mal algo aquí, ya que la primera parte del libro aconseja utilizar Executorsesa reutilización en Threadlugar de crear nuevas instancias.

Entonces, ¿la agrupación de objetos ha quedado obsoleta hoy en día?

usuario10326
fuente

Respuestas:

72

Está en desuso como una técnica general, porque, como notaron, la creación y destrucción de objetos de corta duración per se (es decir, asignación de memoria y GC) es extremadamente barata en las JVM modernas. Por lo tanto, el uso de un conjunto de objetos escritos a mano para sus objetos comunes es más lento, más complicado y más propenso a errores que el simple new. *

Sin embargo, todavía tiene sus usos para objetos especiales cuya creación es relativamente costosa, como conexiones de DB / red, hilos, etc.

* Una vez tuve que mejorar el rendimiento de una aplicación Java que rastrea. La investigación descubrió un intento de usar un grupo de objetos para asignar millones de objetos ... y el tipo inteligente que lo escribió usó un solo bloqueo global para que sea seguro para subprocesos. Reemplazar el grupo por simple newhizo que la aplicación fuera 30 veces más rápida.

Péter Török
fuente
1
Entonces, ¿cómo se puede decidir si la creación de instancias de un objeto es demasiado costosa?
usuario10326
3
Si el objeto consume recursos del sistema operativo (hilos, E / S, memoria compartida, etc.)
kevin cline
13
@ user10326, por medición :-) Si crear sus objetos lleva mucho tiempo y / o están asociados con algún recurso especial, potencialmente limitado, sin memoria, puede considerar la agrupación.
Péter Török
8
@ user10326, IMO en más del 95% de los casos, el criterio anterior hace que sea fácil decidir de antemano si necesita un grupo de objetos. (Además, en casi todos los casos que necesitan un grupo, lo más probable es que use una biblioteca / marco existente, que probablemente ya tenga el grupo de objetos implementado para usted). Por lo demás, todavía es fácil ocultar la creación de objetos, por ejemplo, una fábrica, que luego puede reimplementarse de la forma que mejor le parezca.
Péter Török
2
Punto muy importante hecho por @Peter Torok: muchos frameworks y bibliotecas implementan la agrupación para usted, SIEMPRE asegúrese de que no esté utilizando una biblioteca agrupada antes de implementar la suya.
hromanko
36

La respuesta a la pregunta concreta: "¿La agrupación de objetos es una técnica obsoleta?" es:

No. La agrupación de objetos se usa ampliamente en lugares específicos: agrupación de subprocesos, agrupación de conexiones de bases de datos, etc.

La creación general de objetos nunca ha sido un proceso lento. La agrupación en sí misma consume recursos: memoria y potencia de procesamiento. Cualquier optimización es una compensación.

La regla es:

¡La optimización prematura es malvada!

Pero, ¿cuándo es prematura una optimización dada?

La optimización prematura es cualquier optimización realizada, antes de que haya descubierto un cuello de botella a través de un perfil completo .

Boris Yankov
fuente
2
En efecto. OP dijo "Siempre trato de usarlo tanto como sea posible" - este es el problema, OMI.
nerdytenor
@Boris, entonces, de acuerdo con su segunda oración, ¿no deberíamos objetar las conexiones y subprocesos db del grupo hasta que las descubramos como un cuello de botella a través de la creación de perfiles?
Pacerier
1
@Pac Algunos resultados de perfilado no necesitan una medición constante :-)
David Bullock
9

En situaciones en las que desea evitar la recolección de basura por completo, creo que la agrupación de objetos es la única alternativa viable. Entonces no, no es una técnica obsoleta.

Jer
fuente
1
Y agregaría que es una buena idea evitar GC siempre que los objetos sean lo suficientemente longevos como para pasar a la generación anterior.
Zan Lynx
8

Medida

Depende completamente de su caso de uso, el tamaño de sus objetos, su JVM, sus opciones de JVM, qué GC ha habilitado y una gran cantidad de otros factores.

En resumen: mida antes y mida después. Suponiendo que está utilizando un marco de agrupación de objetos (como el de Apache), no debería ser demasiado doloroso intercambiar entre implementaciones.

Consejo de prueba de rendimiento adicional: deje que la JVM se caliente un poco primero, ejecute las pruebas en una JVM en ejecución varias veces, puede comportarse de manera diferente.

Martijn Verburg
fuente
3
"Deje que la JVM se caliente un poco primero", recuerdo cuando lo único que tenía que "calentarse" era el monitor. Oy, todo lo nuevo es viejo otra vez.
kylben
¡Lo único que necesito para calentar es el café!
Desilusionado el
@ Marijn, ¿cómo dejas que se "caliente"?
Pacerier
Consulte el Marco JMH para obtener una explicación completa ( openjdk.java.net/projects/code-tools/jmh ), pero básicamente debe darle a la JVM la oportunidad de JITAR su código, ejecutar GC antes de su punto de referencia, etc.
Martijn Verburg
8

Esa agrupación en realidad empeora el rendimiento del programa, especialmente en aplicaciones concurrentes, y es aconsejable instanciar nuevos objetos, ya que en las JVM más nuevas, la creación de instancias de un objeto es realmente rápida.

Depende del contexto.


fuente
1
Excelente respuesta y convincente. Yo agregaría (¿tal vez como un asterisco?) Que el reclamo de "24 bytes" se refiere a 4 instancias de flotantes de 4 bytes (16 bytes), más 4 bytes para la referencia del objeto, más 4 bytes para una referencia de bloqueo. Esta es la sobrecarga exacta que elimina su diseño.
strickli
5

No sé si hay una tendencia cambiante aquí, pero ciertamente será el caso de que dependa . Si su clase Java está administrando un recurso externo, como una conexión RMI o cargando un archivo de recursos, etc., entonces ciertamente los costos para la creación de instancias de objetos aún pueden ser altos (¡aunque esos recursos ya pueden estar agrupados para usted!). Como práctica general, estoy de acuerdo con el libro.

Jeremy
fuente
Bueno, ahora no lo sé. Porque incluso en este caso usted describe cuál (antes de leer esto) definitivamente usaría la agrupación, también tendría gastos generales. 1) Nuevas construcciones para manejar la agrupación 2) Sincronización para el objeto de obtención / liberación del grupo 3) mantener el grupo, etc. Así que ahora estoy pensando que tal vez no haya ningún caso de uso que sea útil, excepto, por ejemplo, el almacenamiento en caché de un socket en lugar de abrir uno nuevo cada vez para conectarse al servidor. Y este caso se debe a la red sobrecarga de latencia y no creación de instancias
usuario10326
@ user10326 Sí exactamente. Veo abrir un zócalo como parte de la sobrecarga de instanciación, si es el trabajo de la clase hacer eso y debe inicializarse en el constructor, entonces lo que le preocupa son los impactos de latencia e IO.
Jeremy