Java's Deep Copy Alternatives: Performance Comparative Analysis
Over the last few months, I have been thinking of building a sample project with the primary goal of comparing the performance of different techniques for creating deep copies in Java. The idea was to use the insights from this project and apply them in one of my real-world applications for performance enhancement.
You can find the source code of that sample project here.
The project tries to compare the performances of deep copying Java objects using serialization, reflection and copy constructor.
Disclaimer: It is essential to take into account the various factors. Serialization requires all classes to implement the java.io.Serializable
interface. You need to handle the transient variables. If you are using a copy constructor, you need to give attention to multiple references to the same object and circular references. This article exclusively focuses on performance comparison, keeping the object hierarchy uncomplicated and direct.
Constructing a large object
Performance becomes crucial especially when dealing with the deep copying of sizeable Java objects.
In this context, the project generates a substantial object. Specifically, it constructs an instance of the Company
class, encompassing 5 Department
entities. Each Department
entity further comprises 500 Employee
instances, while each Employee
object has 1 Address
and is associated with 200 Task
entities. The evaluation will reveal how effectively various copying methods can handle this sizeable data structure.
The size of the Company
object encompassing all the child objects in the hierarchy is approximately 15.49 MB. This size was calculated using VisualVM by adding shallow sizes of all child objects as shown in the screenshot below:
Performance Comparative Analysis
I ran the tests on the Windows machine with an Intel(R) i7 1.70 GHz processor and 16 GB RAM.
The table below shows the average timings taken in milliseconds to deep copy the object using three different approaches. Even though the average timings for a technique vary across the number of iterations, the dissimilarities between the three techniques are pretty much the same.
Number of iterations | Avg. time using serialization | Avg. time using reflection | Avg. time using the copy constructor |
1 | 3869 | 1895 | 54 |
5 | 3085 | 1771 | 17 |
10 | 2968 | 1716 | 20 |
It is quite obvious that deep copying with a copy constructor is blazingly fast, while serialization is the most expensive.
However, your choice of technique might depend on the size and complexity of the object structure, performance requirements, availability of time, maintenance overhead etc.
Feel free to use this source code to try out deep copying with your object hierarchies or with some other technique.
Subscribe to my newsletter
Read articles from Nilesh Wani directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by