声明 64 个元素的多个数组比声明 65 个元素的数组快 1000 倍 [英] Declaring multiple arrays with 64 elements 1000 times faster than declaring array of 65 elements

查看:19
本文介绍了声明 64 个元素的多个数组比声明 65 个元素的数组快 1000 倍的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我注意到声明一个包含 64 个元素的数组比声明一个包含 65 个元素的相同类型的数组要快得多(>1000 倍).

Recently I noticed declaring an array containing 64 elements is a lot faster (>1000 fold) than declaring the same type of array with 65 elements.

这是我用来测试的代码:

Here is the code I used to test this:

public class Tests{
    public static void main(String args[]){
        double start = System.nanoTime();
        int job = 100000000;//100 million
        for(int i = 0; i < job; i++){
            double[] test = new double[64];
        }
        double end = System.nanoTime();
        System.out.println("Total runtime = " + (end-start)/1000000 + " ms");
    }
}

这大约需要 6 毫秒,如果我将 new double[64] 替换为 new double[65] 大约需要 7 秒.如果作业分布在越来越多的线程上,这个问题就会变得更加严重,这就是我的问题的根源.

This runs in approximately 6 ms, if I replace new double[64] with new double[65] it takes approximately 7 seconds. This problem becomes exponentially more severe if the job is spread across more and more threads, which is where my problem originates from.

这个问题也会出现在不同类型的数组中,例如 int[65]String[65].大字符串不会出现这个问题:String test = "many characters";,但是当把它改成String test = i + "";

This problem also occurs with different types of arrays such as int[65] or String[65]. This problem does not occur with large strings: String test = "many characters";, but does start occurring when this is changed into String test = i + "";

我想知道为什么会这样,以及是否有可能规避这个问题.

I was wondering why this is the case and if it is possible to circumvent this problem.

推荐答案

您正在观察由 Java VM 的 JIT 编译器完成的优化引起的行为.此行为可通过最多 64 个元素的标量数组触发,并且不会通过大于 64 的数组触发.

You are observing a behavior that is caused by the optimizations done by the JIT compiler of your Java VM. This behavior is reproducible triggered with scalar arrays up to 64 elements, and is not triggered with arrays larger than 64.

在详细介绍之前,让我们仔细看看循环体:

Before going into details, let's take a closer look at the body of the loop:

double[] test = new double[64];

身体没有任何影响(可观察到的行为).这意味着无论是否执行该语句,在程序执行之外都没有区别.整个循环也是如此.所以可能会发生,代码优化器将循环转换为具有相同功能和不同计时行为的(或什么都没有).

The body has no effect (observable behavior). That means it makes no difference outside of the program execution whether this statement is executed or not. The same is true for the whole loop. So it might happen, that the code optimizer translates the loop to something (or nothing) with the same functional and different timing behavior.

对于基准测试,您至少应该遵守以下两个准则.如果你这样做了,差异就会小得多.

For benchmarks you should at least adhere to the following two guidelines. If you had done so, the difference would have been significantly smaller.

  • 通过多次执行基准测试来预热 JIT 编译器(和优化器).
  • 使用每个表达式的结果并将其打印在基准测试的末尾.

现在让我们进入细节.毫不奇怪,对于不大于 64 个元素的标量数组会触发优化.优化是逃逸分析的一部分.它将小对象和小数组放在堆栈上,而不是将它们分配在堆上——或者甚至更好地将它们完全优化掉.您可以在以下 Brian Goetz 于 2005 年撰写的文章中找到有关它的一些信息:

Now let's go into details. Not surprisingly there is an optimization that is triggered for scalar arrays not larger than 64 elements. The optimization is part of the Escape analysis. It puts small objects and small arrays onto the stack instead of allocating them on the heap - or even better optimize them away entirely. You can find some information about it in the following article by Brian Goetz written in 2005:

可以使用命令行选项 -XX:-DoEscapeAnalysis 禁用优化.标量数组的魔法值 64 也可以在命令行上更改.如果按如下方式执行程序,64 和 65 个元素的数组之间将没有区别:

The optimization can be disabled with the command line option -XX:-DoEscapeAnalysis. The magic value 64 for scalar arrays can also be changed on the command line. If you execute your program as follows, there will be no difference between arrays with 64 and 65 elements:

java -XX:EliminateAllocationArraySizeLimit=65 Tests

话虽如此,我强烈反对使用此类命令行选项.我怀疑它在实际应用中是否会产生巨大的差异.我只会在我完全相信必要性的情况下使用它 - 而不是基于某些伪基准测试的结果.

Having said that, I strongly discourage using such command line options. I doubt that it makes a huge difference in a realistic application. I would only use it, if I would be absolutely convinced of the necessity - and not based on the results of some pseudo benchmarks.

这篇关于声明 64 个元素的多个数组比声明 65 个元素的数组快 1000 倍的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆