Java实时性能

ldo*_*dog 12 java performance real-time

我正在使用需要非常高级的图像处理的Java项目.事实上,我正在使用OpenCV进行大部分操作,而我正在使用JNI来包装我需要的OpenCV函数.我对OpenCV给出的性能非常满意,编写OpenCV代码的人应该为代码赢得极大的荣誉.与Java开发人员编写的代码形成鲜明对比.

我开始对我的编程语言的选择持乐观态度,我项目的第一次工作迭代工作得很好,但它的性能远不及实时(每2秒大约1帧).我已经对MY代码进行了一些优化,它帮了很多忙.我已经能够将帧速率提高到大约每秒10-20帧,这很好,但我发现要进行任何进一步的优化我必须重写Java代码来做同样的事情但是10效率提高-20倍.

我对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)); 
}
Run Code Online (Sandbox Code Playgroud)

上面的代码将图像转换为灰度,并获得浮点像素数据,大约1-10ms.如果我想对Java内置函数做同样的事情,转换为灰度本身需要200-300ms,然后抓取浮动像素需要大约50-100ms.这对于实时性能来说是不可接受的.注意为了获得加速,我大量使用按位运算符,Java开发人员不愿意这样做.

我知道他们需要处理一般情况,但即便如此,他们至少不能给出优化选项,或者至少警告这个代码可能执行的速度有多慢.

我的问题是,在开发的最后阶段(我已经进行了第一次迭代,而不是我正在进行第二次迭代,实时执行更多)我应该咬紧牙关切换到C/C++我可以在调整更多东西,或者我应该坚持使用Java并希望事情变得更加实时友好,这样我就不必重写已经实现的Java代码来获得加速.

我真的开始厌恶"优雅"和慢速Java的真实性.那里的课程数量似乎有点矫枉过正.

Bob*_*Gee 15

我已经做了与Java计算机视觉的工作,我可能会downvoted这么说,但它是计算机视觉和实时的东西非常有用的,你只需要知道如何使用它.

潜在优化:

如果您需要帮助优化代码,我很乐意提供帮助 - 例如,我可以告诉您,通过制作方法可能会提升性能

`public static final int getGrayScale(final int pixelRGB){
    return (0.212671f * ((pixelRGB >> 16) & 0xff) + 0.715160f * ((pixelRGB >> 8) & 0xff) + 0.072169f * ((pixelRGB) & 0xff));
}`
Run Code Online (Sandbox Code Playgroud)

并在你的{pixels}循环中使用它.通过使用方法调用,JVM可以更加大量地优化此操作,并且可能更多地优化for循环.

如果你有要刻录的RAM,你可以为所有可能的24位像素像素颜色创建一个输出灰度字节的静态最终查找表.这将是~16 MB的RAM,但是你不必进行任何浮点运算,只需要一个数组访问.这可能会更快,具体取决于您使用的JVM,以及它是否可以优化数组边界检查.

找到类似,更快的图像处理代码的地方:

我强烈建议您查看ImageJ图像处理应用程序的代码(由于StackOverflow被阻止而无法链接)及其库,特别是ij.process.TypeConverter.就像你的代码一样,它在很大程度上依赖于直接阵列操作,只需要进行比特操作最少的额外数组创建.Java2D库(标准JRE的一部分)和Java高级成像(JAI)库(由于StackOverflow被延迟而无法链接)提供了其他方法,可以快速直接对图像数据进行图像处理,而无需每次都进行自己的操作时间.对于Java2D,您只需要小心使用哪些功能.

为什么Java2D库如此间接:

大多数"类别"是由于支持多种颜色模型和存储格式(IE HSB图像,基于浮动的颜色模型,索引颜色模型).间接存在是有原因的,有时实际上提升了性能 - BufferedImage类(例如)直接挂钩到最近VM中的图形内存中,以使某些操作更快.间接让它可以在很多时候从用户屏蔽它.


hha*_*fez 6

我的问题是,在开发的最后阶段(我已经进行了第一次迭代,而不是我正在进行第二次迭代,实时执行更多)我应该咬紧牙关切换到C/C++我可以在调整更多东西,或者我应该坚持使用Java并希望事情变得更加实时友好,这样我就不必重写已经实现的Java代码来获得加速.

你问我应该

  1. 切换到我可以满足我的性能要求的语言.
  2. 坚持Java并希望事情有所改善.

可能还有其他选项......但是选项2看起来并不现实,你不能只是"希望"代码变得更快:p

需要注意的几点:

  1. OpenJDK与Sun JDK没有相同的性能,你试过Sun JDK吗?
  2. 如果您需要完成的性能优化只有几种方法,那么可能值得重新编写它们并坚持使用Java ...