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

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

Для конкретного примера, допустим, я хочу определить переменную NORTH, которая будет массивом MapLocations, представляющие квадраты, которые робот может видеть, если смотреть на север. Если я отдам код, Я могу написать:

public class SightSensor{
  public static MapLocation[] NORTH = {new MapLocation(-2,2),
                    new MapLocation(-1,1),
                        new MapLocation(-1,2),
                        new MapLocation(0,1),
                        new MapLocation(0,2),
                        new MapLocation(0,3),
                        new MapLocation(1,1),                       
                        new MapLocation(1,2),
                        new MapLocation(2,2)};

}

, что означает, что робот может видеть все квадраты в 90-градусной дуге относительно севера на расстоянии в квадрат на 9. Теперь мои роботы могут видеть во всех основных направлениях, а некоторые видят дальше чем другие. Было бы довольно утомительно и, казалось бы, дурным тоном сдавать код каждому возможному прицел (расстояние, направление) пара. Следовательно, я написал функцию

public static MapLocation[] getSensorLocs(int r, Direction dir){ ... bla ... }

, который автоматически вычисляет местоположения, поэтому я могу переписать класс SightSensor как

public class SightSensor{
  public static MapLocation[] NORTH = getSensorLocs(3, Direction.NORTH);
}

Единственная проблема в том, что когда робот пытается использовать переменную NORTH, он должен потратить время для запуска метода getSensorLocs, так что это дороже, чем рукописная версия. Могу ли я заставить эти вычисления выполняться во время компиляции, то есть быть «символически замененными» в соответствующем смысле?

Ответы [ 5 ]

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

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

// 8 bytes per field.
public static MapLocation[] NORTH = locations("\u006a\u0079\u007a\u0089\u008a\u008b\u0099\u009a\u009b\u00aa");

// 57 bytes.
public static MapLocation[] locations(String s) {
    final int len = s.length();
    MapLocation[] locations = new MapLocation[len];
    for (int i = 0; i < len; i++) {
        char ch = s.charAt(i);
        locations[i] = new MapLocation((ch >> 4) - 8, (ch & 0xf) - 8);
    }
    return locations;
}

static class MapLocation {
    public MapLocation(int x, int y) {
        System.out.println("x=" + x + ", y=" + y);
    }
}

печать

x=-2, y=2
x=-1, y=1
x=-1, y=2
x=0, y=1
x=0, y=2
x=0, y=3
x=1, y=1
x=1, y=2
x=1, y=3
x=2, y=2

Примечание: длина строки кодирования не добавляет ни одного байтового кода!.


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

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

Запрашивается не компиляция во время компиляции, а выполнение во время компиляции.

Вы запрашиваете, чтобы NORTH каким-то образом вычислялся во время компиляции, а затем сохранялся как «замороженное» значение в байт-коде.

Это, как правило, невозможно или нежелательно.

Если вы ограничены количеством байт-кода, которое вы можете использовать, тогда рассмотрите представление направлений и т. Д. Не как объекты, а как массивы флагов. Это в основном написание старого кода на C на Java, поэтому он не рекомендуется в качестве общего передового опыта, но все еще довольно распространен в программировании игр (особенно на Java ME)

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

public static MapLocation[] NORTH = getSensorLocs(3, Direction.NORTH); уже оценивается только один раз - почему он запускается каждый раз?Вы уже сделали «предварительное вычисление».

Я не уверен, действительно ли это вопрос оценки.Похоже, вы хотите запускать код во время компиляции, а это вообще не тот язык, который делает.В Java нет препроцессора, что может быть самым близким к тому, что вы имеете в виду.Большинство Java делают такие вещи, как compute, что литерал "5 + 3" равен "8".

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

Вы можете в другом Java-проекте написать генератор кода, генерирующий файл .java.Вместо всех этих new MapLocation вы можете повторно использовать объекты (static final MapLocation ML_M2_1 = new MapLocation(-2, 1);), что поможет больше.Единственный другой способ повысить скорость работы - учесть, что вы создаете данные для поиска.Если вам удастся создать числовую кодировку, например 0xF2 для new MapLocation(-1, 2), вы действительно что-то сохраните.

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

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

...