Java实时性能

Java实时性能,java,performance,real-time,Java,Performance,Real Time,我正在使用Java项目,该项目需要对图像进行非常高级的操作。事实上,我正在使用OpenCV进行大部分操作,我正在使用JNI来包装我需要的OpenCV函数。我对OpenCV提供的性能非常满意,编写OpenCV代码的人应该得到代码的高度赞扬。与我在Java开发人员编写的代码中的体验形成鲜明对比 我一开始对编程语言的选择持乐观态度,我的项目的第一个工作迭代运行得很好,但它的性能远没有达到实时性(大约每2秒1帧)。我对我的代码进行了一些优化,这对我很有帮助。我已经能够将帧速率提高到每秒10-20帧左右,

我正在使用Java项目,该项目需要对图像进行非常高级的操作。事实上,我正在使用OpenCV进行大部分操作,我正在使用JNI来包装我需要的OpenCV函数。我对OpenCV提供的性能非常满意,编写OpenCV代码的人应该得到代码的高度赞扬。与我在Java开发人员编写的代码中的体验形成鲜明对比

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

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)); 
}
for(int i=0;i>32;
字节红色=(字节)((p>>16)和0xff);
字节绿色=(字节)((p>>8)和0xff);
字节蓝色=(字节)((p)和0xff);
字节值=(字节)(0.212671f*红色+0.715160f*绿色+0.072169f*蓝色);
数据[i]=val;
grayFrameData[i]=(val和0x80)+(val和(0x7f));
}
上面的代码将图像转换为灰度,并在大约1-10毫秒内获得浮点像素数据。如果我想用Java内置函数做同样的事情,转换为灰度本身需要200-300毫秒,然后获取浮点像素需要大约50-100毫秒。这对实时性能来说是不可接受的。注意,要获得加速,我需要大量的时间使用逐位运算符,Java开发人员对此避而不谈

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

我的问题是,在开发的这个后期阶段(我已经有了我的第一次迭代,而不是我正在进行的第二次迭代的实时性更强)我应该咬紧牙关,切换到C/C++中,在那里我可以对事情进行更多的微调,还是应该坚持使用Java,希望事情变得更加实时友好,这样我就不必重写已经实现的Java代码来获得加速


我真的开始对“优雅”感到厌恶了Java的速度确实很慢。类的数量似乎有点过头了。

我的建议是,这取决于图像操作相对于整个项目的重要性,以及相对于Java带来的任何优势。显然,您可以用Java编写快速代码(如您所演示的)但是,如果您的项目有80%将包含这样的优化,我肯定会重新考虑Java作为这里的语言选择

另一方面,如果这代表了应用程序的20%,而另外80%是提供此转换的用户功能,那么可能必须完成操作是一个值得的权衡,不必处理您自己的内存管理,也不必使用java为用户提供的任何其他API交互(Web、Swing、SWT,无论您使用什么)

由于垃圾收集器的存在,Java的实时性并不为人所知。这可能也会对你造成伤害,所以要小心

我的问题是,在开发的这个后期阶段(我已经有了我的第一次迭代,而不是我正在进行的第二次迭代的实时性更强)我应该咬紧牙关,切换到C/C++中,在那里我可以对事情进行更多的微调,还是应该坚持使用Java,希望事情变得更加实时友好,这样我就不必重写已经实现的Java代码来获得加速

你是在问我该不该

  • 切换到可以满足性能要求的语言
  • 坚持使用Java,希望事情有所改善
  • 可能还有其他选择……但是选择2似乎不现实,你不能仅仅“希望”代码变得更快:p

    需要注意的几点:

  • OpenJDK的性能不一定和Sun JDK一样,你试过Sun JDK吗
  • 如果您需要在一些方法中进行性能优化,那么可能值得重新编写它们并坚持使用Java

  • 过早优化是万恶之源

    与其抱怨,不如编写一组优化过的库并发布它们,但创建一个针对某个不存在的目标进行了预优化的“参考”java实现是错误的


    参考实现的主要目的是生成可理解、可维护的代码——这是必须的。我认为,人们总是期望在必要时,供应商会分析这个可理解的版本,并重新实现部分以提高速度。

    除了其他人所说的,您还可以对JDK进行优化。I如果您能够提供一个强大的优化,而不牺牲通用性或可读性,我希望您能够在未来的JDK版本中包含您的补丁


    因此,您不必希望JDK变得更好。您可以帮助实现它。

    据我所知,最新版本的Java(或者可能是
    `public static final int getGrayScale(final int pixelRGB){
        return (0.212671f * ((pixelRGB >> 16) & 0xff) + 0.715160f * ((pixelRGB >> 8) & 0xff) + 0.072169f * ((pixelRGB) & 0xff));
    }`