java - 为数组索引赋值和为java中的变量赋值之间的性能差异

标签 java arrays

我正在编写一段代码,其中我对数组值进行一些计算并将结果存储回数组。演示代码如下-

public class Test {
    private int[] x = new int[100000000];
    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        Test t = new Test();
        long start = System.nanoTime();
        for(int i=0;i<100000000;i++) {
            t.testing(i);
        }
        System.out.println("time = " + (System.nanoTime() - start)/1000);
    }

    public void testing(int a) throws Exception {
        int b=1,c=0;
        if(b<c || b < 1) {
            throw new Exception("Invalid inputs");
        }
        int d= a>>b;
        int e = a & 0x0f;
        int f = x[d];
        int g = x[e];
        x[d] = f | g;
    }
 }

程序的主要逻辑在于

int d= a>>b;
int e = a & 0x0f;
x[d] = f | g;

当我测试这段代码时,它花费了 110 毫秒。 但是,如果我将结果分配给一个变量,而不是将结果分配回 x[d]

int h = f | g;

只用了 3 毫秒。

我只想将结果分配回数组,但这会大大影响性能。 这是一个时间紧迫的程序。

所以我想知道在 Java 中是否有任何替代数组的方法或任何其他方法可以避免这种阻碍?

我在默认的 sun JVM 配置下测试了这段代码。

附言我尝试了 UNSAFE API,但没有帮助。

最佳答案

您需要注意的是 JVM 将代码优化为空,因为它没有做任何有用的事情。

在您的情况下,您在 110 毫秒或每次调用大约 1.1 纳秒内执行 1 亿次调用。给定单个内存到 L1 缓存的访问需要 4 个时钟周期,这是非常快的。在您的测试中,您在 3 毫秒内获得了 1 亿,这表明每次调用需要 0.03 纳秒或大约时钟周期的 1/10。对我来说这听起来不太可能,我希望如果将循环的长度加倍,它仍然需要 3 毫秒。即,您正在计算检测和消除代码所需的时间。

您遇到的一个基本问题是您有一个大小为 400 MB 的数组。这不适用于 L1、L2 或 L3 缓存。相反,它可能进入主存储器,这通常需要 200 个时钟周期。最好的选择是减小数组的大小,使其至少适合您的 L3 缓存。你的三级缓存有多大?如果是 24 MB,请尝试将阵列减少到 16 MB,您应该会看到性能提升。

关于java - 为数组索引赋值和为java中的变量赋值之间的性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20684383/

相关文章:

java - eclipse 看不到我的 lenovo S650 手机

java - 如何解决Eclipse中Android应用程序的Maven配置问题?

javascript - 按结尾数字对以数字结尾的字符串进行排序

java - 更改 Java 数组的维数

c - 高效地对 int 数组进行位移?

java - 为许多对象初始化引用变量?

java - 加载加密 key

java - 当我对我之前在代码中执行过的同一 WebElement 执行 click() 时,出现空指针异常

c - 将多个字符串分别放入一个数组中

arrays - Swift:音频文件数组