2012-01-02 1 views
0

Я пытаюсь понять компиляцию и вычисление времени выполнения в java. У меня есть следующие перечисления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)}; 

нет накладных расходов. Я не понимаю разницы. Составляет ли компилятор странный вид вычисления «точно в срок»?

+0

Можете ли вы объяснить, как вы измеряете накладные расходы? –

+0

Кроме того, ваш пример не компилируется; вам нужно какое-то другое выражение в 'getLocs', потому что теперь есть пути без возвращаемого значения (когда' dir' не является ни NORTH, ни SOUTH) –

+0

Nail, извините за это, попытался упростить код. Измерение в байтекоде. – andyInCambridge

ответ

3

Похоже, что стоимость, которую вы видите, представляет собой стоимость загрузки класса: при первом обращении к классу класс-загрузчик загружает свой двоичный файл (.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)

+0

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

+0

Какую стоимость вы видите в байте-коде? –

+0

Около 10000 байт-кода – andyInCambridge

2

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

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

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

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

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

Real differences between "java -server" and "java -client"?

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

+0

Спасибо за ответ. Я прихожу из C++, поэтому я еще не знаю этих деталей. – andyInCambridge

0

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

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

Вместо SightSensor.getLocs(someDir) вы затем вызвать someDir.getLocs().

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

Смежные вопросы