|
Replies:
7
-
Last Post:
May 27, 2005 10:55 AM
by: hoschek
|
|
|
|
|
|
|
Why clone much slower than new instance?
Posted:
May 25, 2005 7:28 PM
|
|
|
I write a simple test for compare the clone() and new instance.
public class Main { private boolean flag = true; private String string = "Hello"; private int i = 0; static class Child extends Main implements Cloneable { private boolean flag2 = false; private String string2 = "World"; private int i2 = -1; } }
Now, when new instance Child for 1000000 times, it cost 40ms, but the clone operation cost for about 430ms. (in JDK1.5.0-b64). It shows that clone doesnt provide an idea speed.
Can somebody tell me why?
|
|
|
|
|
|
|
Re: Why clone much slow than new instance?
Posted:
May 25, 2005 10:51 PM
in response to: wangzaixiang
|
|
|
I guess it is the implementation of Object.clone() method and the JNI cost.
If so, why not inline some JNI call? and makes it as quickly as normal JIT method. It looks that Hotspot inline Math.sin/cos etc method to instruction directly.
|
|
|
|
|
|
|
|
Re: Why clone much slow than new instance?
Posted:
May 26, 2005 5:40 AM
in response to: wangzaixiang
|
|
|
> I guess it is the implementation of Object.clone() > method and the JNI cost.
I know Object.clone() is marked 'native', but I expect that doesn't necessarily mean it uses JNI.
I expect it's marked native because the JVM never executes a clone() method in the normal way, but instead substitutes some highly-optimized machine code for it. (In the jargon, clone() is intrinsified.) Does anybody know if this is true?
I'd be surprised if they used JNI for such an important method.
|
|
|
|
|
|
|
|
Re: Why clone much slow than new instance?
Posted:
May 26, 2005 11:55 AM
in response to: lucretius2
|
|
|
Actually in the HotSpot JVM Object.clone() is not currently heavily optimized, while new instance is. You can feel free to file an RFE about this in the bug database. You can work around this problem by overriding clone() and manually allocate the new instance and assign the data into it. In fact, I think this is already probably necessary once your data structures get more complicated, which is why slow performance of Object.clone() hasn't shown up on our performance radar.
Ken Russell, Java HotSpot VM Group, Sun Microsystems
P.S. Here's a revised version of your test case which gets rid of startup transients.
public class Main {
private boolean flag = true;
private String string = "Hello";
private int i = 0;
static class Child extends Main implements Cloneable {
private boolean flag2 = false;
private String string2 = "World";
private int i2 = -1;
}
private static int count = 1000000;
public static void testClone() throws CloneNotSupportedException {
Child child = new Child();
int res = 0;
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Child child2 = (Child) child.clone();
res += child2.i2;
}
long stopTime = System.currentTimeMillis();
System.out.println("" + count + " clones took " +
(stopTime - startTime) + " ms (dummy result = " + res + ")");
}
public static void testNewInstance() {
int res = 0;
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Child child = new Child();
res += child.i2;
}
long stopTime = System.currentTimeMillis();
System.out.println("" + count + " new operations took " +
(stopTime - startTime) + " ms (dummy result = " + res + ")");
}
public static void main(String[] args) throws CloneNotSupportedException {
testClone();
testClone();
testClone();
testNewInstance();
testNewInstance();
testNewInstance();
}
}
|
|
|
|
|
|
|
|
Re: Why clone much slow than new instance?
Posted:
May 26, 2005 7:16 PM
in response to: kbr
|
|
|
> You can work around this problem by overriding clone() and manually allocate the new instance and assign the data into it. In fact, I think this is already probably necessary once your data structures get more complicated, which is why slow performance of Object.clone() hasn't shown up on our performance radar.
Of course it will works but it makes the world more complex. as we see, the clone operation is equals to "allocate the memory, copy the origin area to it", and the new operation is "allocate the memory and calls the constructor to initialize it", the clone will be more effiectly in most case, that is the value of why a "clone" method exists.
|
|
|
|
|
|
|
|
Re: Why clone much slow than new instance?
Posted:
May 27, 2005 5:42 AM
in response to: wangzaixiang
|
|
|
> You can work around this problem by overriding > clone() and manually allocate the new instance and > assign the data into it.
But the trouble with this is that you need to know the object's type at compile-type. The beauty of clone() is you don't need to know what type of object you're cloning. You can probably emulate this using reflection, but I expect it would be awkward and slow.
BTW, I hope cloning of arrays doesn't suffer from the same speed problems. This is pretty much the only time I use clone(), because of various other problems with clone() (as spelt out in Josh Bloch's Effective Java). Surely most people, like me, have been assuming that cloning an array is faster than creating a new instance and using System.arraycopy().
|
|
|
|
|
|
|
|
Re: Why clone much slow than new instance?
Posted:
May 27, 2005 10:48 AM
in response to: lucretius2
|
|
|
> BTW, I hope cloning of arrays doesn't suffer from the > same speed problems. This is pretty much the only > time I use clone(), because of various other problems > with clone() (as spelt out in Josh Bloch's Effective > Java). Surely most people, like me, have been > assuming that cloning an array is faster than > creating a new instance and using System.arraycopy().
System.arraycopy is way faster than array.clone(). I actually discussed this with Josh Bloch and we filed a bug report (which hasn't been fixed so far). For example it shows up as a wild hotspot when doing Arrays.sort(). Bottom line: use new() with arraycopy() if speed matters.
|
|
|
|
|