2010-05-28 3 views
2

Для переменной, используемой в функции, которая называется очень часто и для реализации в 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++; 
     } 
    } 
} 

Я знаю, что есть разница, как доступ к статическим по сравнению с не-статической переменной класса, но я не знаю, что это повлияет скорость. Я также помню, где-то читал, что в функциональных переменных можно получить доступ быстрее, но я не знаю, почему и где я это читал.

Справочная информация по вопросу: некоторые функции рисования в играх называются чрезмерно часто, и даже небольшая разница в времени доступа может влиять на общую производительность, когда переменная используется в довольно большом цикле.

Update

I установка небольшой тест (код ниже) и запустил его на реальном устройстве, чтобы увидеть, что результаты похожи. Я выполнил 10000 вызовов функции, которая за 10000 раз переходила к переменной.

  • если переменная была в-функции потребовалось ~ 9250 мс для запуска
  • если переменная принадлежит к классу, потребовалось ~ 21700 мс запустить
  • если переменная принадлежит к классу, но был static it tool ~ 210000 мс для запуска.

Я не знаю, насколько актуальны результаты теста, если они будут проводиться в реальной программе и если в игре нет другого внешнего фактора. Но, предполагая, что они это делают, поскольку он соответствует наиболее часто просматриваемому представлению здесь, тогда существует значительная разница между временами доступа.

Опасается ли это преждевременной оптимизации? Возможно, но также полезно использовать как можно больше функциональной переменной. Даже копирование переменной класса в функциональную, похоже, может повлиять на время выполнения.

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++; 
     } 
    } 
+5

Преждевременная оптимизация. – Robin

+1

Согласитесь с Робин. Особенно, если картина является узким местом, объявление переменной по-другому не будет вашей серебряной пулей. –

+0

Ваш тест испорчен, поскольку test3 запускается после теста2, который запускается после теста1. test1, возможно, разогрел кеш-тест2, а test3 оказался быстрее. Вы должны запускать их в независимых прогонах. –

ответ

8

Они имеют совершенно различную семантику - вы хотите, чтобы значение, чтобы быть частью состояния класса, часть состояния экземпляров класса, или локальной по отношению к методу?

У JIT есть больше возможностей для оптимизации последней версии, поскольку она знает все о том, где может использоваться переменная (и не нужно беспокоиться о том, что другие потоки обращаются к ней). Я бы сказал, что это , вероятно, будет самым быстрым.

Вы должны действительно протестировать, хотя и, в общем, сначала написать наиболее читаемый код и посмотреть, действительно ли у вас есть узкое место, прежде чем пытаться выполнить такую ​​микро-оптимизацию.

+0

Я согласен с семантикой, но переменная используется только внутри функции. Мне было интересно, может ли это сделать быстрее. Я буду выполнять некоторые тесты и публиковать результаты. – ADB

+0

Я не думаю, что вы можете рассчитывать на оптимизацию JIT на Java ME. –

+2

@ Майкл: Возможно, нет - но трудно понять, как дать платформе более жесткий контроль над переменной заставит ее работать * хуже *. –

2

Лично я думаю, что вы не увидите заметной разницы между этими тремя. Почему бы просто не попробовать все три и выполнить некоторые тесты производительности? Это единственный способ узнать наверняка, так как JVM оптимизирует вещи под обложками, может быть неинтуитивным.

Мне трудно поверить, что это ваше узкое место в производительности. Моим подходом было бы написать его самым логичным способом и искать оптимизацию в другом месте.

3

Вы должны тщательно прокомментировать код, прежде чем подумать об этом виде микро-оптимизации. А затем реализуйте и измерьте эффекты любых возможных микрооптимизаций.

Слишком сложно предсказать, какие (если есть!) Из трех версий будут быстрее на вашей конкретной платформе.

0

Или вы могли бы просто использовать традиционный цикл, который высвобождает эту память, как только цикл заканчивается:

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

Я также помню, что читал где-то, что в-функции переменные могут быть доступны быстрее, но я не знаю почему

Локальные переменные могут храниться в регистре, самой быстрой памяти, которая существует. Если у вас нет очень умных полей JIT, экземпляры и классы должны находиться в основной памяти (или кеше), так как они могут быть видны другим потокам.

Так как это также лучшее решение с точки зрения чистоты кода, вы обязательно должны пойти с локальной переменной.

0

Если ваша целевая платформа не имеет какую-то очень нечетной реализации виртуальной машины Java, порядок производительности:

  • локальных переменная
  • статический/объект член

Причина, локальные переменные предлагают наилучшей производительностью является то, что они:

  • Специально поддерживаются более короткие байткоды с помощью JVM
  • Для доступа к ним не требуется дополнительной информации (члены объекта должны быть адресованы с использованием этой ссылки, в то время как статические члены нуждаются в ссылке на класс)
  • Только видимые для локальной нити и, таким образом, ЛТ может выполнять различные оптимизации на них (например, поместив их в регистр)

Он может также отметить, что параметры метода обрабатывают так же, как локальные переменные на уровне байт-кода.