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

java中为数组索引赋值和为变量赋值的性能差异,java,arrays,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

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

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;
    }
 }
当我测试这段代码时,花了110毫秒。 但是,如果我将结果赋给变量作为

int h = f | g;
只花了3毫秒

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

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

我在默认的sunjvm配置下测试了这段代码


另外,我尝试了不安全的API,但它没有帮助。

这是因为
h
是一个局部变量,在堆栈上分配,而数组存储在主内存中,写入速度慢得多


还要注意,如果这是一个真正的高性能应用程序,那么应该将主逻辑放在for循环中,并避免调用方法的开销。指令可以为您内联,但您不应该依赖它。

这是因为
h
是一个局部变量,在堆栈上分配,而数组存储在主内存中,写入速度要慢得多


还要注意,如果这是一个真正的高性能应用程序,那么应该将主逻辑放在for循环中,并避免调用方法的开销。这些指令可以为您内联,但您不应该依赖它。

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

在您的情况下,您将在110毫秒内执行1亿次呼叫,或每次呼叫约1.1纳秒。如果一个内存到一级缓存的访问需要4个时钟周期,那么这相当快。在你的测试中,你在3毫秒内获得了1亿,这意味着每次通话需要0.03纳秒,或者大约1/10的时钟周期。对我来说,这听起来不太可能,我预计如果循环长度增加一倍,仍然需要3毫秒。也就是说,您正在计时检测和消除代码所需的时间


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

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

在您的情况下,您将在110毫秒内执行1亿次呼叫,或每次呼叫约1.1纳秒。如果一个内存到一级缓存的访问需要4个时钟周期,那么这相当快。在你的测试中,你在3毫秒内获得了1亿,这意味着每次通话需要0.03纳秒,或者大约1/10的时钟周期。对我来说,这听起来不太可能,我预计如果循环长度增加一倍,仍然需要3毫秒。也就是说,您正在计时检测和消除代码所需的时间


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

可能会发生很多事情。首先,试着连续多次运行程序的每个版本,并取平均值。其次,在Java中为数组赋值是一个执行错误检查的方法调用(如在必要时抛出ArrayIndexOutOfBoundsException)。这自然会比变量赋值慢一点。如果您有一个非常敏感的代码,请考虑使用JNI进行数值操作:这通常会使阵列逻辑更快。

可能会发生很多事情。首先,试着连续多次运行程序的每个版本,并取平均值。其次,在Java中为数组赋值是一个执行错误检查的方法调用(如在必要时抛出ArrayIndexOutOfBoundsException)。这自然会比变量赋值慢一点。如果您有一个非常敏感的代码,请考虑使用JNI进行数值操作:这通常会使您的数组逻辑更快。

使用字典怎么样?我想知道您是在什么环境下运行此功能的?对我来说,你得到的结果似乎不太可能。在Java中衡量性能需要首先“预热JVM”;我会进行三次测量,并查看第三次测量的数据。@Gimby-我在预热后也进行了测试,结果大致相同。使用字典怎么样?我想知道你是在什么环境下进行的?对我来说,你得到的结果似乎不太可能。在Java中衡量性能需要首先“预热JVM”;我会进行三次测量,并查看第三次测量的数据。@Gimby-我在预热后也进行了测试,结果大致相同。这似乎是基于15年前计算机的情况得出的信息。从那以后情况发生了变化。堆栈内存不是存储在主内存中吗?为什么堆栈内存的写入速度比堆内存快?@Brandon堆栈变量更可能完全存在于寄存器中。@当您不知道自己在说什么时,不值得进行下一票表决。运行时可以通过多种不同的方式优化代码。堆栈区域未映射到任何
int h = f | g;