How clone has more performance than object creation
Asked Answered
A

6

11

I'm trying to understand what's happening underneath the clone() method in java, I would like to know how is better than doing a new call

public class Person implements Cloneable {

    private String firstName;
    private int id;
    private String lastName;

    //constructors, getters and setters

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person p = (Person) super.clone();
        return p;
    }

}

this is my clone code i would like to know what's happening underneath and also what's the difference between a new call because.

this is my client code

    Person p = new Person("John", 1, "Doe");
    Person p2 = null;
    try {
         p2 = (Person) p.clone();
    } catch (CloneNotSupportedException ex) {
        Logger.getLogger(clientPrototype.class.getName()).log(Level.SEVERE, null, ex);
    }
    p2.setFirstName("Jesus");
    System.out.println(p);
    System.out.println(p2);
Anatropous answered 25/2, 2015 at 17:29 Comment(5)
Why do you think that clone() has better performance than object creation? That's not true.Steading
It's also not a good idea to use clone() in the first place.Satyr
What would you use instead of clone, also, why is not true clone has better performance?Anatropous
One non-performance-related advantage of .clone() (assuming it uses Object.clone() underneath) is that it produces an object with the same runtime class as the object it is called on, whereas if you use new you would be hard-coding at compile-time the class of object you are creating, which may not be the same as the exact runtime class of the object (the object's class can be a subclass of the compile-time type of a variable that points to it).Rigamarole
As always when talking about clone, try to avoid it at all cost. It is a broken feature, super easy to introduce bugs and extremely hard to implement correct. And even harder to maintain a correct implementation with inheritance in place (Effective Java has a nice read on that topic). There are much more safer and better ways for creating copies. For example by introducing a copy constructor to your class.Underwaist
U
11

If you need a copy, call clone(), if not, call a constructor.
The standard clone method (java.lang.Object.clone()) creates a shallow copy of the object without calling a constructor. If you need a deep copy, you have to override the clone method.
And don't worry about performance.
Performance depends on the contents of the clone method and the constructors and not from the used technique(new or clone) itself.

Edit: Clone and constructor are not really alternatively to each other, they fullfill different purposes

Urbano answered 25/2, 2015 at 21:15 Comment(6)
So what you are saying is new an object and cloning an object has the same impact?Anatropous
No, the impact depends on the contents of the constructor and the clone method. If your class has only few members, a simple default-ctor and no override of clone(), the impact may be similar. My recommendation is to use clone only if you need a copy of an existing object. Clone and constructor are not really alternatively to each other, they fullfill different purposes.Urbano
so if i want a clone of an existing object will it have more performance than newing a new object with the same values as my object ?Anatropous
That cannot be answered generally. If your class has only primitives and you don't override clone() and your constructor processes some work, clone() is maybe faster. But this discussion is a little bit useless, because you should use the technique you need, and not the fastest one or maybe fastest one. Construction and cloning are different concepts and you should choose the tecnique which fits your needs.Urbano
mmm, so okay but let's say that i want the fastest in this case, would clone make it faster somehow?Anatropous
Test it. Create a million of objects with the contructor and another million with clone() with time measurement. But you have to do it for all types of objects you want to handle.Urbano
R
7

I have created simple benchmark for class Person:

public class Person {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

And got the following results:

Benchmark             Mode  Cnt     Score       Error   Units

MyBenchmark.viaClone  avgt   10     10.041 ±    0.059   ns/op
MyBenchmark.viaNew    avgt   10      7.617 ±    0.113   ns/op

This simple benchmark demonstrates that instantiating new object and setting corresponding properties from source object takes 25% less time than cloning it.

Rhetorical answered 13/7, 2017 at 7:43 Comment(1)
I submitted a PR to your repo, added a Clone Constructor method to the benchmark. When benchmarking on a macbook pro w/ jdk11, "Score" was ~4 ns/op across all 3 methods, performance difference negligible. github.com/aaabramov/benchmark-it/pull/12Arnulfo
B
6
public void testPerformance(){
    SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd");
    long start = System.currentTimeMillis();
    for(int i = 0; i < 1000000; i++){
        SimpleDateFormat localSdf = (SimpleDateFormat)sdf.clone();
    }
    System.out.println("Cloning : " + (System.currentTimeMillis() - start) + " ms");

    start = System.currentTimeMillis();
    for(int i = 0; i < 1000000; i++){
        Object localSdf = new SimpleDateFormat("yyyy-MM-dd");
    }
    System.out.println("Creating : " + (System.currentTimeMillis() - start) + " ms");

}

Cloning : 302 ms Creating : 885 ms

Backwater answered 19/6, 2017 at 11:59 Comment(4)
The user wanted to know what is going on under the hood of the clone function not just the performance.Audreyaudri
It is not about object cloning vs constructor performance, it's more about SimpleDateFormat, because this specific constructor is very heavy. I would recommend to have it's static instance for reuse.Scalise
@Scalise static has a whole host of haters who conflate it with the sins of global state, since almost any context might be a reentrant one. Final is a friend.Compensation
I'm not questioning programming practices, I just mean that SimpleDateFormat constructor is very heavy and slow. See askldjd.com/2013/03/04/simpledateformat-is-slowScalise
S
1

Joachim is right. If you need copy use Clone, If you need a seprate object (for a seprate person) you should use new and create a new Object instead.

'More Performance' is subjective and may not be the right term here. What happens in clone is the underlying objects are shared, i.e. they have 2 seprate references to the same memory location. So effectively you save up creating objects and memory. Remember Deep copy / Shallow Copy?

Sundstrom answered 27/2, 2015 at 9:51 Comment(2)
can you explain me more this thing you said about 2 object en memory having the same memory location? how come then if i edit one the other one is not changed? wouldn't it be two references with two separate memory location?Anatropous
Here is a decent explanation: javarevisited.blogspot.in/2013/09/…Sundstrom
F
1

My requirement is to create 1000's of object for a class. All those objects shares most of the properties in common. Hence I decided to create one base object with common properties and clone it and on cloned object set object specific properties. What will be the performance impact on this?. I tried out same example as above, with different approach and I noticed no much stable performance difference. Here are my code and results.

import java.util.*;
import java.util.stream.*;
import java.text.*;
public class Test{
    public static void main(String[] args){

        try{
            SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd");
            long start = System.currentTimeMillis();
            SDFHolder holder = new SDFHolder();
            holder.setSdf(sdf);
            for(int i = 0; i < 1000000; i++){
                SDFHolder locHolder = (SDFHolder)holder.clone();
            }
            System.out.println("Cloning : " + (System.currentTimeMillis() - start) + " ms");
            start = System.currentTimeMillis();
            for(int i = 0; i < 100000000; i++){
                SDFHolder locHolder = new SDFHolder();
                locHolder.setSdf(sdf);
            }
            System.out.println("Creating : " + (System.currentTimeMillis() - start) + " ms");
        } catch(Exception e){
            e.printStackTrace();
        }
    }
}
class SDFHolder implements Cloneable {
    private SimpleDateFormat sdf;

    public void setSdf(SimpleDateFormat sdf){
        this.sdf = sdf;
    }

    public SimpleDateFormat getSdf(){
        return this.sdf;
    }

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

And results are

C:\Users\thangaraj.s\Desktop>java Test
Cloning : 15 ms
Creating : 0 ms

C:\Users\thangaraj.s\Desktop>java Test
Cloning : 16 ms
Creating : 0 ms

C:\Users\thangaraj.s\Desktop>java Test
Cloning : 0 ms
Creating : 15 ms

C:\Users\thangaraj.s\Desktop>java Test
Cloning : 0 ms
Creating : 16 ms

C:\Users\thangaraj.s\Desktop>java Test
Cloning : 16 ms
Creating : 0 ms

So, I don't think there is a huge performance impact on these but gives more concise code in-case of my requirement.

Fifth answered 24/8, 2017 at 6:43 Comment(0)
B
0

It also depends on the number of fields and complex stored structures that will need to be cloned using the deep method. I came across a similar task where you need to give away a typical object as quickly as possible in 99% of cases and the object is very complex in content. Therefore, I am now considering the option to store the prepared binary object as a response template, and clone it and deploy it to the desired class. In theory, it can be faster, especially cloning for structurally complex objects. but I don't know how effective it will be to convert a cloned object from a binary format to a class

Behindhand answered 30/7, 2023 at 9:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.