Я пытаюсь оптимизировать свой код, но это доставляет мне проблемы. У меня есть этот список объектов:
List<DataDescriptor> descriptors;
public class DataDescriptor {
public int id;
public String name;
}
1700 объектов с уникальным идентификатором (0-1699) и некоторым именем, оно используется для декодирования того, какой тип данных я получу позже.
Метод, который я пытаюсь оптимизировать, работает следующим образом:
public void processData(ArrayList<DataDescriptor> descriptors, ArrayList<IncomingData> incomingDataList) {
for (IncomingData data : incomingDataList) {
DataDescriptor desc = descriptors.get(data.getDataDescriptorId());
if (desc.getName().equals("datatype_1")) {
doOperationOne(data);
} else if (desc.getName().equals("datatype_2")) {
doOperationTwo(data);
} else if ....
.
.
} else if (desc.getName().equals("datatype_16")) {
doOperationSixteen(data);
}
}
}
Этот метод вызывается примерно миллионы раз при обработке файла данных, и каждый раз, когда входящийDataList содержит около 60 элементов, поэтому этот набор операторов if / elses выполняется около 60 миллионов раз.
Это занимает около 15 секунд на моем рабочем столе (i7-8700).
Изменение кода для проверки целочисленных идентификаторов вместо строк, очевидно, сбрасывает несколько секунд, что хорошо, но я надеялся на большее :) Я попробовал профилирование с использованием VisualVM, но для этого метода (с тестированием строк) говорится, что 66% времени тратится на "Self time" (который, я считаю, будет всем этим тестированием строк?) почему он не говорит, что он в методе String.equals?) и 33% тратится на descriptors.get
- это просто получить из ArrayList, и я не думаю, что смогу оптимизировать его дальше, кроме tryi Чтобы изменить структуру данных в памяти (все же, это Java, поэтому я не знаю, поможет ли это много).
Я написал приложение "простой тест", чтобы изолировать сравнение String против int. Как я и ожидал, сравнение целых чисел было примерно в 10 раз быстрее, чем String.equals, когда я просто запускал приложение, но когда я профилировал его в VisualVM (я хотел проверить, не слишком ли медленно работает тест производительности ArrayList.get), как ни странно, оба метода потребовали точно такое же количество времени. При использовании образца VisualVM вместо профиля приложение завершало работу с ожидаемыми результатами (целые числа были в 10 раз быстрее), но VisualVM показывал, что в его примере оба типа сравнения занимали одинаковое количество времени.
В чем причина? для получения таких совершенно разных результатов при профилировании и нет? Я знаю, что есть много факторов, есть JIT, и профилирование может помешать этому и т. Д. c. - но, в конце концов, как вы профилируете и оптимизируете код Java, когда инструменты профилирования изменяют работу кода? (если это так)