当前位置: 首页 > 知识库问答 >
问题:

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

江浩慨
2023-03-14

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

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;

当我测试这段代码时,它花了110ms。但是如果我把它赋给一个变量,而不是将结果返回到x[d]

int h = f | g;

只花了3毫秒。

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

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

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

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

共有3个答案

常培
2023-03-14

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

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

颜楚青
2023-03-14

有很多事情可能会发生。首先,试着连续多次运行每个版本的程序,并取平均值。其次,在Java中分配数组是一种执行错误检查的方法调用(例如在必要时抛出ArrayIndexOutOfBoundsExctive)。这自然会比变量分配慢一点。如果你有一段非常时间敏感的代码,考虑使用JNI进行数值操作:http://docs.oracle.com/javase/6/docs/technotes/guides/jni/.这通常会让你的数组逻辑更快。

贺博厚
2023-03-14

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

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

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

 类似资料:
  • 本文向大家介绍详解PHP变量传值赋值和引用赋值变量销毁,包括了详解PHP变量传值赋值和引用赋值变量销毁的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了PHP变量传值赋值和引用赋值变量销毁的具体代码,供大家参考,具体内容如下 php中,上面的代码,变量是怎么存放的呢? 上面的代码变动下,将变量b赋值给变量a,会发生什么? 问题来了,$a = $b,那么是将变量a的指针指向了变量b指针所

  • 原文: http://exploringjs.com/impatient-js/ch_variables-assignment.html 下面这些是 JavaScript 声明变量的主要方式: let用来声明可变变量。 const用来声明常量(不可变变量)。 在ES6之前,还有var。但它有些怪癖,所以最好在现代JavaScript程序中避免使用它。你可以在“Speaking JavaScript

  • 主要内容:声明变量,变量赋值Java 语言是强类型(Strongly Typed)语言,强类型包含以下两方面的含义: 所有的变量必须先声明、后使用。 指定类型的变量只能接受类型与之匹配的值。 这意味着每个变量和每个表达式都有一个在编译时就确定的类型。类型限制了一个变量能被赋的值,限制了一个表达式可以产生的值,限制了在这些值上可以进行的操作,并确定了这些操作的含义。 常量和变量是 Java 程序中最基础的两个元素。常量的值是不

  • = 赋值操作符(它的左右两边不能有空白符) 不要搞混了 = 和 -eq,-eq 是比赋值操作更高级的测试。注意:等于号(=)根据环境的不同它可能是赋值操作符也可能是一个测试操作符。 例子 4-2. 简单的变量赋值 1 #!/bin/bash 2 # 裸变量 3 4 echo 5 6 # 什么时候变量是“裸”的?比如说,变量名前面没有$? 7 #当变量被赋值

  • 通过函数构造函数创建变量时它们似乎被声明为VAL。由于VAL不能重新赋值(出于某些原因,我需要这样做),我想知道是否有办法在函数之前的一行代码中将变量声明为var,然后通过函数赋值。 请记住,我昨天才开始学习静态编程语言。我对所有替代方案都持开放态度。 公共趣味单打(enemyhealth:Int,enemyattack:Int,enemyname:String) 当我尝试重新分配敌人的健康时,我