Я работаю с Java-проектом, который требует очень продвинутых манипуляций с изображениями. Фактически, я делаю большую часть манипуляций с использованием OpenCV, и я использую JNI, чтобы обернуть нужные мне функции OpenCV. Я очень доволен производительностью, которую дает OpenCV, люди, которые написали код OpenCV, заслуживают большого уважения за код. В резком контрасте с тем, что я испытываю с кодом, написанным разработчиками Java.
Я начал с оптимизма в отношении выбора языка программирования, моя первая рабочая итерация проекта работает нормально, но его производительность не приближается к реальной (получая около 1 кадра в 2 секунды). Я провел некоторые оптимизации Мой код и его очень помогли. Я смог увеличить частоту кадров примерно до 10-20 кадров в секунду, и это здорово, но я обнаружил, что для дальнейшей оптимизации мне нужно переписать код Java, чтобы сделать то же самое, но 10 -20x эффективнее.
Я потрясен тем, как разработчики Java уделяют очень мало внимания производительности, особенно при написании классов для классов, связанных с Media. Я скачал 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 / C ++, где Я могу настраивать вещи намного больше, или я должен придерживаться Java и надеяться, что все станет более дружественным в реальном времени, так что мне не придется переписывать уже реализованный Java-код для ускорения.
Я действительно начинаю испытывать отвращение к тому, насколько "классной" и медленной является Java. Количество классов там кажется чрезмерным.