7

我从其他几份报告中读到,人们通常在一个简单的基本 JNI 调用中得到大约4-80 ns :

是什么让 JNI 调用变慢?

对于琐碎的本机方法,去年我发现在我的 Windows 桌面上平均调用 40 ns,在我的 Mac 桌面上平均调用 11 ns ..

使用 JNI 可能提高性能?

然而,JNI 调用通常需要大约 30 ns ..

当我在我的 JNI 代码中调用简单方法时(简单我的意思是返回类型 int 的时间参数不超过一个参数),我得到的往返调用时间(使用 System.nanoTIme 测量)在 50,000-80,000 ns 之间。

如果我做一个虚拟机“热身”并在计时之前运行几百次调用,我仍然会得到大约2000-4000 ns(低于 800-1000)。(如上所述,我听说其他人报告 < 100 ns .. 并且在频繁通话时确实会高出 10-20 倍。)

这是正常速度吗?什么可能导致我的本机代码被调用这么慢?

更新:

JNIEXPORT jint JNICALL Java_com_snap2d_gl_RenderControl_correctGammaNative
  (JNIEnv *env, jobject obj, jint pixel) {
    return X2D_correctGamma(pixel, 1.0f);
}

其中 X2D_correctGamma(int,float) 是一种校正像素伽马值的方法(自发布以来我已经实现了本机代码)。

Java基准测试:

    for(int i = 0; i < 100; i++) {
        long t1 = System.nanoTime();
        correctGammaNative(0xFFF);
        long t2 = System.nanoTime();
        System.out.println(t2 - t1);
    }

那是“热身”代码。大多数 println 在初始调用后读取 800-1000ns。

不幸的是,我可能不得不放弃它,因为它应该用于渲染,每秒调用数千次会将帧速率降低到 1 FPS。

系统信息:

行为类似:JDK1.6.0_32(64 位)、JDK1.7.0_04(64 位)和 JRE1.7.0_10(32 位)

Windows 7 64 位

16GB 内存

i7-3770 四核 CPU @ 3.4-3.9ghz

GNU GCC MinGW 编译器(32 位和 64 位)

4

2 回答 2

7

这是正常速度吗?

不。如果你真的在每次 JNI 调用中获得 50,000-80,000 ns,那么就会发生一些奇怪的事情。

什么可能导致我的本机代码被调用这么慢?

不知道。它几乎可以是任何东西。但是,如果您向我们展示本机代码和 Java 代码,我们将能够更好地进行解释。

我的钱将用于这根本不是 JNI 调用的问题。相反,我希望它是您进行基准测试的方式的产物。您可以做(或不做)很多事情,这些事情会导致 Java 基准测试产生虚假结果。我们需要查看您的基准测试代码。


好的,您的更新表明您之前报告的时间(50,000-80,000 或 2000-4000)不正确或不相关。考虑到以下情况,800-1000ns 的时间听起来是合理的。

我认为您的基准测试存在三个缺陷。

  • 您正在尝试测量几纳秒级的时间间隔。但是您的测量没有考虑到调用System.nanoTime()需要很长时间。您需要做的是测量在每对调用之间进行几千或几百万次 JNI 调用所需的时间System.nanoTime(),然后计算并打印平均值。

  • 您的代码不会将进行 JNI 调用所花费的时间与执行调用主体所花费的时间分开。(或者也许它确实......你还没有向我们展示那个代码。)。我怀疑伽玛校正将花费比 JNI 调用开销更长的时间。

  • 你的热身不够。令人怀疑的是,您运行代码的时间是否足以让 JIT 编译启动。此外,您的基准代码仅限于单个方法调用这一事实意味着即使 JIT 编译器确实运行了,您也有可能“ d 从不调用该方法的 JIT 编译版本。将基准代码放入一个方法中并重复调用该方法。

于 2013-01-11T01:33:15.607 回答
0

热身时间太短了。在约 10.000 次调用后会触发一个方法。另外将循环体移动到一个方法,因为“就地”无限循环抖动和单一方法抖动之间存在差异。

于 2013-09-05T09:29:30.120 回答