我从其他一些报告中读到,人们通常会在一个普通的基本JNI呼叫上 4-80 ns :
对于琐碎的原生方法,去年我在Windows桌面上发现平均呼叫时间为40 ns,而我的Mac桌面上则为11 ns。
来自Possible increase of performace using JNI?
然而,JNI呼叫通常需要大约30 ns ..
当我在我的JNI代码中调用简单方法时(简单来说,我的意思是时间int返回类型int只有一个参数),我得到的往返调用时间(用System.nanoTIme测量)在50,000之间 - 80,000 ns。
如果我进行VM“预热”并在计时之前运行几百次,我仍然会得到 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);
}
这是“热身”代码。初次调用后,大多数printlns读取800-1000ns。
不幸的是,我可能不得不废弃它,因为它应该用于渲染,每秒调用数千次会使帧速率降至1 FPS。
系统信息:
行为类似:JDK1.6.0_32(64位),JDK1.7.0_04(64位)和JRE1.7.0_10(32位)
Windows 7 64位
16GB RAM
i7-3770四核CPU @ 3.4-3.9ghz
GNU GCC MinGW编译器(32位和64位)
答案 0 :(得分:7)
这是正常的速度吗?
没有。如果你真的每个JNI呼叫获得50,000-80,000 ns,那就会发生一些奇怪的事情。
什么原因导致我的本机代码被调用得那么慢?
不知道。它几乎可以是任何东西。但是如果你向我们展示了本机代码和Java代码,我们就能更好地解释它。
我的钱将在这不是JNI呼叫的问题。相反,我希望它是您进行基准测试的方式的人工制品。您可以做很多事情(或者不做)会导致Java基准测试产生虚假结果。我们需要查看您的基准测试代码。
好的,您的更新表明您之前报告的时间(50,000-80,000或2000-4000)不正确或无关紧要。鉴于以下情况,800-1000ns的计时听起来似乎是合理的。
我认为你的基准测试有三个缺陷。
您正在尝试测量几纳秒的时间间隔。但是你的测量没有考虑到的是对System.nanoTime()
的调用需要很长时间。您需要做的是衡量在每对System.nanoTime()
次呼叫之间进行几千或几百万次JNI呼叫所需的时间,然后计算并打印平均值。
您的代码不会将执行JNI调用所花费的时间与执行调用主体所花费的时间分开。 (或者它可能......并且你没有向我们展示那些代码。)我怀疑伽马校正将比JNI呼叫开销花费更长的时间。
你的热身不足。令人怀疑的是你运行的代码已经足够长时间以便JIT编译了。此外,你的基准代码仅限于单个方法调用的事实意味着即使JIT编译器运行了,你也可能会' d从不调用该方法的JIT编译版本。将基准代码放入方法并重复调用该方法。
答案 1 :(得分:0)
热身太短了。在约10.000次调用之后进行一次方法。另外,将循环体移动到一个方法,因为“就地”无限循环jitting和jitting单个方法之间存在差异。