声明变量的哪种方式最快?

时间:2010-05-28 14:31:35

标签: java blackberry java-me

对于在经常被调用的函数中使用的变量以及在黑莓上的J2ME中实现的变量(如果改变了某些东西,你能解释一下吗?)

class X {
    int i;
    public void someFunc(int j) {
        i = 0;
        while( i < j ){
            [...]
            i++;
        }
    }
}

class X {
    static int i;
    public void someFunc(int j) {
        i = 0;
        while( i < j ){
            [...]
            i++;
        }
    }
}

class X {
    public void someFunc(int j) {
        int i = 0;
        while( i < j ){
            [...]
            i++;
        }
    }
}

我知道如何访问静态类和非静态类变量,但我不知道它会影响速度。我还记得在某处读取函数变量可以更快地访问,但我不知道为什么以及在哪里读到它。

问题的背景:游戏中的某些绘画功能被过度调用,即使在较大的循环中使用变量时访问时间的微小差异也会影响整体性能。

更新

我设置了一个小测试(下面的代码)并在真实设备上运行它以查看结果是什么样的。我对一个循环10000次访问变量的函数运行了10000次调用。

  • 如果变量是函数,则运行<9250 ms
  • 如果变量属于该类,则运行时间为~21700 ms
  • 如果变量属于类但是是静态的,则工具运行~210000 ms。

我不知道测试的结果有多相关,如果它们能够保存在真实世界的程序中,并且没有其他外部因素在起作用。但是,假设他们这样做,因为它匹配这里最常见的视图,那么访问时间之间存在相当大的差异。

这是否属于过早优化?也许,但它似乎也是尽可能使用函数内变量的有用指南。即使将类变量复制到函数变量,似乎也会影响执行时间。

   final static int MAX = 10000;
   private void runTest()
   {
       long startTime = System.currentTimeMillis();
       for(int count = 0; count < MAX; count++)
           test1(MAX);
       test1.setText(""+(System.currentTimeMillis()-startTime));

       startTime = System.currentTimeMillis();
       for(int count = 0; count < MAX; count++)
           test2(MAX);
       test2.setText(""+(System.currentTimeMillis()-startTime));

       startTime = System.currentTimeMillis();
       for(int count = 0; count < MAX; count++)
           test3(MAX);
       test3.setText(""+(System.currentTimeMillis()-startTime));

   }

   void test1(int j)
   {
       int i = 0;
       while(i < j)
       {
           i++;
       }
   }
   int i2;
   void test2(int j)
   {
       i2 = 0;
       while(i2 < j)
       {
           i2++;
       }
   }
   static int i3;
   void test3(int j)
   {
       i3 = 0;
       while(i3 < j)
       {
           i3++;
       }
   }

6 个答案:

答案 0 :(得分:8)

它们具有完全不同的语义 - 您是希望该值是类的状态的一部分,是类的实例的一部分,还是方法的本地?

JIT有更多机会优化最后一个版本,因为它知道可以使用变量的所有内容(并且不需要担心其他线程访问它)。我会说可能是最快的。

你应该测试一下 - 通常,首先编写最易读的代码,看看在尝试这种微优化之前你是否确实遇到了瓶颈。

答案 1 :(得分:3)

在您甚至认为关于此类微优化之前,您应该彻底剖析代码。然后,实施并衡量任何可能的微观优化的效果。

很难预测这三个版本中哪些(如果有的话)会在您的特定平台上更快。

答案 2 :(得分:2)

就个人而言,我认为你不会发现三者之间有任何明显的差异。为什么不试试这三个并运行一些性能测试?这是您可以肯定知道的唯一方法,因为JVM优化内容的方式可能不直观。

我发现很难相信这是你的性能瓶颈。我的方法是以最合乎逻辑的方式编写它,并在其他地方寻找优化。

答案 3 :(得分:1)

  

我还记得读到某个地方   可以访问函数内变量   更快,但我不知道为什么

局部变量可以保存在寄存器中,这是存在的最快内存。除非你有一个非常聪明的JIT,实例和类字段必须在主内存(或缓存)中,因为它们对其他线程是可见的。

从代码清洁度的角度来看,它也是最好的解决方案,你绝对应该使用局部变量。

答案 4 :(得分:0)

或者您可以使用传统的for循环,在循环结束后立即回收此内存:

class X {
    public void someFunc(int j) {
        for(int i = 0; i < j; i++){
            [...]
        }
    }
}

答案 5 :(得分:0)

除非您的目标平台有一些非常奇怪的JVM实现,否则性能顺序为:

  • 本地变量
  • 静态/对象成员

局部变量提供最佳性能的原因是:

  • JVM的短字节码特别支持
  • 访问它们不需要任何其他信息(对象成员必须使用此引用进行寻址,而静态成员需要类引用)
  • 仅对本地线程可见,因此JIT可以对它们执行各种优化(例如将它们放入寄存器)

值得注意的是,方法参数与字节码级别的局部变量的处理方式相同。