JNI Performance受到简单原语的影响

时间:2014-05-16 17:59:09

标签: performance java-native-interface

我有一个带有以下签名的JNI方法:

JNIEXPORT jboolean JNICALL Java_MovieWriter_addFrameN(JNIEnv *env, jobject obj, jintArray jFrameBuffer, jlong jDuration);

此方法属于使用本机代码导出影片的程序。程序调用此方法向电影添加帧。 jFrameBuffer是包含像素数据的int [],jDuration是帧的持续时间。简单。

在短片中,一切似乎都运转正常。然而,对于5000+帧的电影,性能会受到影响(例如,执行此方法需要大约1秒钟,而通常情况下,对于相同数量的像素,它会在很短的时间内执行);并最终Java程序崩溃了,留下了我的以下hs日志(我只包括顶部,让我知道你是否想看到整个事情):

# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 691200 bytes for AllocateHeap
# Possible reasons:
#   The system is out of physical RAM or swap space
#   In 32 bit mode, the process size limit was hit
# Possible solutions:
#   Reduce memory load on the system
#   Increase physical memory or swap space
#   Check if swap backing store is full
#   Use 64 bit Java on a 64 bit OS
#   Decrease Java heap size (-Xmx/-Xms)
#   Decrease number of Java threads
#   Decrease Java thread stack sizes (-Xss)
#   Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.
#
#  Out of Memory Error (memory/allocation.inline.hpp:61), pid=1880, tid=4008
#
# JRE version: Java(TM) SE Runtime Environment (7.0_45-b18) (build 1.7.0_45-b18)
# Java VM: Java HotSpot(TM) Client VM (24.45-b08 mixed mode windows-x86 )
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#

我简化了问题以缩小问题范围,我的方法体现在如下:

JNIEXPORT jboolean JNICALL Java_MovieWriter_addFrameN(JNIEnv *env, jobject obj, jintArray jFrameBuffer, jlong jDuration) {

    jsize jLength = env->GetArrayLength(jFrameBuffer);
    int length = (int)jLength;
    long duration = (long)jDuration;

    //add a dummy frame
    HRESULT hr = S_OK;
    DWORD* pixels = new DWORD[length];
    for (DWORD j = 0; j < length; j++) {
        pixels[j] = 0x0000FF00;
    }
    hr = writer.addFrame(pixels, duration, true);
    delete[] pixels;
    return SUCCEEDED(hr);
}

我发现如果我对lengthduration的值进行硬编码而不是将它们分别链接到jni值jLengthjDuration,那么性能问题就会出现问题不会发生。

int length = 640 * 480; // (int)jLength;
long duration = 10000000 / 25; // (long)jDuration;

这对我来说太惊人了。任何人都可以解释发生了什么以及如何解决问题?我甚至无法将基元从Java传递到C而没有性能问题的事实看起来很荒谬。我一定是做错了。

观察程序内存使用情况(使用任务管理器),表明它不会持续增加,所以我不相信我在任何地方都有任何重大泄漏,并且它远远低于内存限制我能成功击中做其他操作。

1 个答案:

答案 0 :(得分:1)

好的,这就是发生的事情:确实是一个误解的例子。

我遇到性能延迟的原因&#39;是双重的:

  1. 当持续时间来自JNI时,它变化了......有时它很短,例如1/25秒,其他时间很长,例如3秒。当它很长时,Windows Media Foundation(我用它来编写帧)会将其分解为帧速大小的片段 - 所以需要3秒的持续时间帧3秒长,写入时间比1长1倍/ 25秒帧,如果帧速率是每秒25帧。所以,这是我认为的性能延迟的一部分,但实际上,它只是做了更多的工作。精细。这是有道理的。

  2. 第二个方面与以下事实有关:在向我的Windows Media Foundation IMFSinkWriter发送大约100,000帧之后,它会陷入困境。这是神秘的关键。事实证明,需要每秒调用一次IMFSinkWriter-&gt; NotifyEndOfSegment以防止这种情况发生。在任何地方我都没有看到这个记录,男孩这样做会让我感到非常悲伤。