0

大家好,我已将 ArrayList 源代码从 java.util 包复制到我自己的包中。但我发现它比原来的 java.util.ArrayList 运行得更好。

测试代码:

@Test
public void jdkApiPerformance() {
    long startTime = System.nanoTime();
    java.util.ArrayList<Object> list = new java.util.ArrayList<Object>();
    long costTime = System.nanoTime() - startTime;
    System.out.println("jdkPerformance cost " + costTime + "ns.");
}

@Test
public void myApiPerformance() {
    long startTime = System.nanoTime();
    question.jdk.ArrayList<Object> list = new question.jdk.ArrayList<Object>();
    long costTime = System.nanoTime() - startTime;
    System.out.println("apiPerformance cost " + costTime + "ns.");
}

该测试的输出如下:

jdk性能消耗10263ns。
api 性能消耗 1244158ns。

显然,我的 api 运行速度比 JDK api 慢。

然后我为此测试添加了一个@Before 方法:

@Before
public void setUp() {
    new java.util.ArrayList<Object>();
    new question.jdk.ArrayList<Object>();
}

这种情况下的输出发生了变化:

jdk性能消耗9932ns。
api 性能花费 1324ns。

我的 api 运行速度比 JDK api 快!!?

对于这种情况,我真的很困惑。请帮助我。谢谢。

4

2 回答 2

2

1)使用System.nanoTime()可能会给您带来扭曲的结果,因为它取决于操作系统的调度程序粒度:

此方法提供纳秒精度,但不一定提供纳秒分辨率(即值更改的频率) - 不保证分辨率至少与 currentTimeMillis() 的分辨率一样好。

2) 要进行有意义的基准测试,您必须先预热JVM

3) 对于研究,您可以使用以下基准库之一:

4) 一般来说,您的问题的答案是:的,在某些情况下,Sun/Oracle 的 JVM 热替换了一些 JDK 代码,例如Math.sqrt()针对给定操作系统/硬件优化的实现。

于 2013-03-05T02:47:42.143 回答
1
  • JVM 按需加载类。由于 java.util.ArrayList 是一个如此基础的类,它很可能在您的基准测试开始之前已经加载,但 question.jdkArrayList 可能是第一次使用。这涉及到磁盘 I/O 来读取类文件,这本身比创建新实例花费的时间要多几个数量级。此外,java.util.ArrayList 更有可能被 JIT 编译器优化。

  • 根据其 javadoc,System.nanoTime() 具有“纳秒精度,但不一定是纳秒精度”。用它来测量微秒级的延迟充其量是偶然的。此外,它测量的是挂钟时间,而不是 CPU 时间。如果您的 cpu 被占用(例如,在您的开发环境中绘制控制台视图),这将计入报告的时间。

于 2013-03-05T02:50:40.620 回答