class DummyInteger {
private int i;
public DummyInteger(int i) {
this.i = i;
}
public int getI() {
return i;
}
}
long start = System.nanoTime();
DummyInteger n = new DummyInteger(10);
long end = System.nanoTime();
long duration = end - start;
System.out.println(duration);
前面的代码产生以下输出:
341000
鉴于:
long start = System.nanoTime();
ArrayList a = new ArrayList();
long end = System.nanoTime();
long duration = end - start;
System.out.println(duration);
产生以下输出:
17000
现在,我的问题是,为什么我们在运行时间上观察到这种差异,即使DummyInteger
类完成的工作最多与ArrayList
执行的工作一样多。构造函数?是否与预编译的ArrayList代码有关?或者是影响处理时间的其他因素?
谢谢。
- 编辑 -
我认为比较两种不同类型的对象的问题会出现,但是,即使使用以下代码,与创建ArrayList
相比也是如此:
class IntList {
int [] elementData;
public IntList() {
elementData = new int [20];
}
}
long start = System.nanoTime();
IntList n = new IntList();
long end = System.nanoTime();
long duration = end - start;
System.out.println(duration);
考虑到结果仍然相同,在这种情况下,由于执行了某些检查,创建ArrayList
的开销应该更大,并且可以通过源代码。
还有一点需要注意的是,我在两个不同的运行中运行这两个代码,这消除了JVM初始化可能产生的任何开销。
答案 0 :(得分:8)
为什么我们在运行时间中观察到这种差异?
因为您的测量没有意义:
nanotime
的分辨率对于您正在测量的操作来说太低了 - 它们可能需要几纳秒的时间nanotime
的分辨率接近1 ms 以下是我采用更强大的方法得到的结果:创建一个新的Integer需要大约6纳秒,而创建一个默认大小(10)的ArrayList在我的机器上大约需要19纳秒。
DummyInteger创建:
Run result "newInteger": 6.064 ±(95%) 0.101 ±(99%) 0.167 nsec/op
Run statistics "newInteger": min = 6.007, avg = 6.064, max = 6.200, stdev = 0.081
Run confidence intervals "newInteger": 95% [5.964, 6.165], 99% [5.897, 6.231]
创建列表:
Run result "newList": 19.139 ±(95%) 0.192 ±(99%) 0.318 nsec/op
Run statistics "newList": min = 18.866, avg = 19.139, max = 19.234, stdev = 0.155
Run confidence intervals "newList": 95% [18.948, 19.331], 99% [18.821, 19.458]
修改强>
我的"更强大的方法"也有一个缺陷,创造实际上被厚脸皮的JIT优化了......上面的新结果虽然结论相似:这些都是非常快的操作。
答案 1 :(得分:4)
加载课程是您可以做的最昂贵的事情之一。 (特别是对于没有做太多工作的类)许多内置类将在程序启动之前使用,因此不需要再次加载它们。当你使用该类时,它的代码就会变暖。
考虑以下示例,其中您提到的三个类是重复创建的
static class DummyInteger {
private int i;
public DummyInteger(int i) {
this.i = i;
}
public int getI() {
return i;
}
}
static class IntList {
int[] elementData;
public IntList() {
elementData = new int[20];
}
}
public static void main(String... ignored) {
timeEach("First time", 1);
for (int i = 1000; i <= 5000; i += 1000)
timeEach(i + " avg", i);
for (int i = 10000; i <= 20000; i += 10000)
timeEach(i + " avg", i);
}
public static void timeEach(String desc, int repeats) {
long time1 = System.nanoTime();
for (int i = 0; i < repeats; i++) {
List l = new ArrayList();
}
long time2 = System.nanoTime();
for (int i = 0; i < repeats; i++) {
DummyInteger di = new DummyInteger(i);
}
long time3 = System.nanoTime();
for (int i = 0; i < repeats; i++) {
IntList il = new IntList();
}
long time4 = System.nanoTime();
System.out.printf("%s: ArrayList %,d; DummyInteger %,d; IntList %,d%n",
desc, (time2 - time1) / repeats, (time3 - time2) / repeats, (time4 - time3) / repeats);
}
使用Java 7更新21和-XX:+PrintCompilation
89 1 java.lang.String::hashCode (55 bytes)
89 2 java.lang.String::charAt (29 bytes)
First time: ArrayList 41,463; DummyInteger 422,837; IntList 334,986
1000 avg: ArrayList 268; DummyInteger 60; IntList 136
120 3 java.lang.Object::<init> (1 bytes)
2000 avg: ArrayList 321; DummyInteger 75; IntList 142
3000 avg: ArrayList 293; DummyInteger 63; IntList 133
123 4 Main::timeEach (152 bytes)
124 5 java.util.AbstractCollection::<init> (5 bytes)
124 6 java.util.AbstractList::<init> (10 bytes)
125 7 java.util.ArrayList::<init> (44 bytes)
4000 avg: ArrayList 309; DummyInteger 64; IntList 175
126 8 java.util.ArrayList::<init> (7 bytes)
127 9 Main$DummyInteger::<init> (10 bytes)
127 10 Main$IntList::<init> (13 bytes)
5000 avg: ArrayList 162; DummyInteger 70; IntList 149
10000 avg: ArrayList 0; DummyInteger 0; IntList 0
20000 avg: ArrayList 0; DummyInteger 0; IntList 0
您可以看到性能提升ArrayList是最慢的。最后,JIT确定不使用对象,不需要创建。然后循环为空,不需要运行,因此平均时间下降到0。
答案 2 :(得分:1)
现在,我的问题是,为什么我们在跑步中观察到这种差异 时间,即使DummyInteger类完成的工作似乎是 最多与ArrayList构造函数执行的一样多?
因为这个基准很糟糕。你不能在1次跑步中说什么。
是否与预编译的ArrayList代码有关?
没有
答案 3 :(得分:0)
您正在比较两种不同类型对象的时间性能,即arraylist和Your Dummyobject,这就是时间统计数据不同的原因。现在让我们来讨论你的问题
创建预先实现的java类的对象要快得多 创建自定义对象?
它不是正确的声明,因为预先实现的java也是一种自定义对象,但是由其他人为您创建(就像您自己创建自定义对象一样)。所以不是 预先实现的java类vs自定义对象,但实际上取决于在对象创建期间发生的操作。