Я работаю с Java-проектом, который требует очень продвинутых манипуляций с изображениями. Фактически, я делаю большую часть манипуляций с помощью OpenCV, и я использую JNI для обертывания функций OpenCV, которые мне нужны. Я очень доволен производительностью OpenCV, люди, которые написали код OpenCV, заслуживают большого вознаграждения за код. В отличие от того, что я испытываю с кодом, написанным разработчиками Java.
Я начал оптимистично относиться к выбору моего языка программирования, моя первая рабочая итерация проекта прекрасно работает, но его производительность нигде не приближается к реальному времени (получается около 1 кадра за 2 секунды). Я сделал некоторые оптимизации МОЙ код и его помогли. Мне удалось увеличить частоту кадров до 10-20 кадров в секунду, что отличает меня, но я обнаружил, что для дальнейших оптимизаций я должен переписать код Java, чтобы сделать то же самое, но 10 -20x более эффективно.
Я потрясен тем, как разработчики Java уделяют очень мало внимания производительности, особенно при написании классов для связанных с медиа классов. Я загрузил OpenJDK, и я изучаю функции, которые я использую. Например, существует функция под классом Raster, называемая getPixels (...), и она получает пиксели изображения. Я ожидал, что эта функция будет высоко оптимизированной функцией в исходном коде, с несколькими вызовами System.arrayCopy для дальнейшей оптимизации производительности. Вместо этого я обнаружил чрезвычайно "классный" код, где они называют 5-6 разных классов и 10-20 разных методов, чтобы выполнить то, что я могу сделать в одной строке:
for (int i =0; i < n; i++) {
long p = rawFrame[i];
p = (p << 32) >>> 32;
byte red = (byte) ((p >> 16) & 0xff);
byte green = (byte) ((p >> 8) & 0xff);
byte blue = (byte) ((p) & 0xff);
byte val = (byte)(0.212671f * red + 0.715160f * green + 0.072169f * blue);
data[i] = val;
grayFrameData[i] = (val & 0x80) + (val & (0x7f));
}
Приведенный выше код преобразует изображение в оттенки серого и получает данные с поплавковым пикселем примерно в 1-10 мс. Если бы я хотел сделать то же самое с встроенными функциями Java, то преобразование в оттенки серого займет 200-300 мс, а затем захват пикселей с плавающей точкой займет около 50-100 мс. Это неприемлемо для работы в реальном времени. Примечание, чтобы получить ускорение, я активно использую побитовые операторы, от которых Java отступает.
Я понимаю, что они должны обрабатывать общий случай, но даже в этом случае они не могут по крайней мере дать варианты оптимизации или, по крайней мере, предупреждение о том, как медленный этот код может выполнять.
Мой вопрос в том, что на этом позднем этапе разработки (у меня уже есть первая итерация, а не я работаю над второй, которая больше работает в режиме реального времени), я должен укусить пулю и переключиться на C/С++, где Я могу настроить мелодию намного больше, или я должен придерживаться Java и надеюсь, что все станет более дружественным в реальном времени, так что мне не придется переписывать уже реализованный Java-код, чтобы получить ускорение.
Я действительно начинаю испытывать отвращение к тому, как на самом деле "классный" и медленный Java. Количество классов там похоже на перебор.