компиляция Java в сравнении с вычислениями во время выполнения - PullRequest
0 голосов
/ 03 января 2012

Я пытаюсь понять, что компиляция и вычисления во время выполнения в Java.У меня есть следующее перечисление

public enum SightSensor{

  NORTH (new MapLocation[]{new MapLocation(0,1), 
                         new MapLocation(0,2),
                         new MapLocation(0,3)}),
  SOUTH (new MapLocation[]{new MapLocation(0,-1), 
                        new MapLocation(0,-2),
                        new MapLocation(0,-3)});

  private final MapLocation[] locs;

  SightSensor(MapLocation[] locs){
    this.locs = locs;
  }

  public static MapLocation[] getLocs(Direction dir){
    if (dir == Direction.NORTH)
      return NORTH.locs;
    if (dir == Direction.SOUTH)
      return SOUTH.locs;
  }
};

Словами, я хочу определить постоянное отображение между Направлением и массивом MapLocations.(Возможно, это неправильный способ сделать это? Я новичок в Java.) Теперь, если я напишу

MapLocation[] locs = SightSensor.getLocs(Direction.SOUTH_WEST);

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

MapLocation[] locs = new MapLocation[]{new MapLocation(0,1),
                           new MapLocation(0,2),
                           new MapLocation(0,3)};

, то никаких накладных расходов не будет.Я не понимаю разницу.Компилятор выполняет какие-то странные вычисления точно в срок?

Ответы [ 3 ]

3 голосов
/ 03 января 2012

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

Кроме того:

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

Как вы измерили эту стоимость? Практически невозможно измерить временные затраты на одну операцию. Вы можете измерить время, необходимое для выполнения проходов xM через цикл, а затем разделить, чтобы получить амортизированную стоимость. Однако измерить одну операцию сложно: возможно, вы получаете цикл сбора мусора, переключение контекста, связанного с потоком, и т. Д. Кроме того, JIT (Just In Time) компилятор не запускает первый раз при выполнении оператора, поэтому измерение одна операция обычно дает вам гораздо более высокую стоимость, чем амортизированная стоимость по сравнению с N операциями.

FWIW, я бы написал getLocs() следующим образом:

public static MapLocation[] getLocs(Direction dir) {
  return valueOf(dir.name()).locs;
}

В качестве альтернативы вы можете использовать замену перечисления SightSensor на переменную типа EnumMap:

EnumMap<Direction, MapLocation[]> map = new EnumMap(Direction.class);
map.put(Direction.NORTH, new MapLocation[] {  new MapLocation(0, 1), 
                                              new MapLocation(0, 2),
                                              new MapLocation(0, 3) });
map.put(Direction.NORTH, new MapLocation[] {  new MapLocation(0, -1), 
                                              new MapLocation(0, -2),
                                              new MapLocation(0, -3) });

Тогда getLocs() звонки просто становятся map.get(dir)

2 голосов
/ 03 января 2012

Выполняет ли компилятор какие-то странные вычисления точно по времени?

Да, среда выполнения Java использует статистику для оптимизации кода во время работы:

http://docs.oracle.com/javase/6/docs/technotes/tools/share/jstat.html

Ничего странного в этом нет.

Это также может быть уместно:

Реальные различия между "java -server" и "java -client "?

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

0 голосов
/ 03 января 2012

Это на самом деле не ответ, а совет: сделайте getLocs нестатичным и просто верните locs текущего перечисления:

public MapLocation[] getLocs(){
    return locs;
}

Вместо SightSensor.getLocs(someDir), после чего вы вызываетеsomeDir.getLocs().

Таким образом, вам не нужно перечислять всех членов перечисления.

...