make java performance copy deep-copy cloning

make - java copy object no reference



ClonaciĆ³n profunda de objetos Java(no frijoles) (4)

Dudo que haya mucho que pueda hacer para mejorar el rendimiento significativamente al seguir los enfoques que ha mencionado. Lamentablemente, lleva tiempo copiar un objeto.

Pensando levemente lateralmente, y claramente dependiendo de la cantidad de memoria que tenga y también la proporción de lectores a escrituras (especialmente si tiene muchos lectores para cada escritura), ¿qué tal crear un caché de copias?

El proyecto en el que estoy trabajando actualmente tiene muchos objetos que se serializan para obtener una copia profunda del objeto existente. Esto funciona bien hasta que tengamos varias llamadas en tiempo de ejecución, en algunos casos tenemos 100, 200 o incluso 1000 llamadas entre componentes y aquí es donde nos topamos con un dolor de cabeza de rendimiento.

La razón histórica para copiar estos objetos que se clonan es que dos componentes diferentes que trabajan en los mismos objetos bajo diferentes funcionalidades no deberían cambiarse, por ejemplo, los cambios en la UI Swing no deberían cambiar los valores del objeto en backend hasta que se presione el botón guardar o sincronizar.

Tenemos una base de código bastante grande, pensé que si escribiera clon basado en la reflexión funcionaría más rápido en comparación con la serialización, pero debido a nuestras complejas jerarquías de objetos o por alguna otra razón, este enfoque es aún más lento.

También intenté usar CloneUtils (proyecto sourceforge), que también es más lento (no estamos usando Hibernate en absoluto). Spring BeanUtils no es una opción (doy por hecho que solo utiliza frijoles, es decir, introspección y en caso de que lo use si algún campo está expuesto utilizando un acceso no estándar, no podremos copiarlos).

Alguien tiene alguna idea, mejorar el rendimiento mientras trabaja en diferentes copias. Tenemos una opción que acelerará las cosas en caso de que proporcionemos nuestros propios métodos de copia, en lugar de la serialización, pero eso tiene un inconveniente de actualizar estos métodos cada vez y si olvidamos, podríamos perder la funcionalidad.


Lo que describes es un enfoque de escopeta para administrar el estado mutable. Intentar hacer una clonación más rápida solo te dará mejoras limitadas (digamos hasta un orden de magnitud). Además, ¿cómo se clona un socket, una transmisión o una conexión de base de datos?

Lo que realmente necesita es refactorizar su aplicación con la separación adecuada de comandos / consultas. De esta forma sabrá dónde está cambiando sus objetos y dónde no. Puede usar pruebas unitarias para verificar esto si no está seguro.

Hay una serie de técnicas que pueden ayudarte: puedes cambiar algunos de tus objetos para que sean inmutables (para que puedas compartirlos de forma natural, creando nuevas copias en mutación); puede hacer que los objetos mutables implementen interfaces de solo lectura y utilicen la vista RO en la GUI, etc.


Puede evitar la reflexión por generación dinámica de clases, por ejemplo, usando cglib . Para cada clase que use, generaría una "clase cloner" que contiene el código necesario para la copia. Esto haría innecesaria la reflexión, siempre que todos los campos sean, al menos, privados del paquete y coloque la clase de copiadora en el mismo paquete. Necesitarías un ctor predeterminado y tampoco campos finales.

Aquí, la serialización tiene una ventaja, ya que crea objetos usando sun.misc.Unsafe .

Implementar un método deepClone en cada clase también podría ser una opción. Incluso podría combinarse con la idea de la clase cloner.


Solo dale una pista sobre cómo puedes mejorar el rendimiento en casos como este: usa un patrón de prototipo si aún no lo estás usando. Podrías obtener algo de rendimiento.