bgr*_*nks 7 c java performance java-native-interface
我从其他几个报告中读到,人们通常会在一个简单的基本JNI呼叫上大约4-80 ns:
对于琐碎的原生方法,去年我发现在我的Windows桌面上平均调用40 ns,在我的Mac桌面上调用11 ns.
然而,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);
}
Run Code Online (Sandbox Code Playgroud)
其中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);
}
Run Code Online (Sandbox Code Playgroud)
这是"热身"代码.初次调用后,大多数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位)
这是正常速度吗?
不.如果你真的在每个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编译版本.将基准代码放入方法并重复调用该方法.