草庐IT

Java JNI 调用比预期慢(至少 2 毫秒/调用)

coder 2024-03-19 原文

我从其他几份报告中读到,人们通常在 4-80 ns 上花费一个普通的、基本的 JNI 调用:

来自 What makes JNI calls slow?

For trivial native methods, last year I found calls to average 40 ns on my Windows desktop, and 11 ns on my Mac desktop ..

来自 Possible increase of performace using JNI?

However JNI calls often take around 30 ns ..

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

如果我对 VM 进行“预热”并在计时之前运行调用数百次,我仍然会得到大约 2000-4000 ns(低于 800-1000)。 (如上所述,我听说其他人报告 < 100="" ns..="" 并且在频繁调用时加起来确实比这高="" 10-20="">

这是正常速度吗?是什么导致我的 native 代码调用速度如此之慢?

更新:

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) 是一种校正像素 Gamma 值的方法(自发布以来我已经实现了 native 代码)。

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 内存

i7-3770 四核 CPU @ 3.4-3.9ghz

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

最佳答案

Is this normal speed?

没有。如果您真的每次 JNI 调用获得 50,000-80,000 ns,则说明发生了一些奇怪的事情。

What could be causing my native code to be called so much slower?

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

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


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

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

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

  • 您的代码没有将进行 JNI 调用所花费的时间与执行调用主体所花费的时间分开。 (或者也许它确实如此……而您还没有向我们展示该代码。)。我怀疑 gamma 校正将比 JNI 调用开销花费更长的时间。

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

关于Java JNI 调用比预期慢(至少 2 毫秒/调用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14269798/

有关Java JNI 调用比预期慢(至少 2 毫秒/调用)的更多相关文章

  1. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  4. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

    我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

  5. ruby-on-rails - ruby 日期方程不返回预期的真值 - 2

    为什么以下不同?Time.now.end_of_day==Time.now.end_of_day-0.days#falseTime.now.end_of_day.to_s==Time.now.end_of_day-0.days.to_s#true 最佳答案 因为纳秒数不同:ruby-1.9.2-p180:014>(Time.now.end_of_day-0.days).nsec=>999999000ruby-1.9.2-p180:015>Time.now.end_of_day.nsec=>999999998

  6. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  7. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  8. ruby - 如何找到调用当前方法的方法 - 2

    如何找到调用此方法的位置?defto_xml(options={})binding.pryoptions=options.to_hifoptions&&options.respond_to?(:to_h)serializable_hash(options).to_xml(options)end 最佳答案 键入caller。这将返回当前调用堆栈。文档:Kernel#caller.例子[0]%rspecspec10/16|===================================================62=====

  9. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  10. ruby - 为什么当我调用类的实例方法时,初始化不显示为方法? - 2

    我正在写一篇关于在Ruby中几乎一切都是对象的博客文章,我试图通过以下示例来展示这一点:classCoolBeansattr_accessor:beansdefinitialize@bean=[]enddefcount_beans@beans.countendend所以从类中我们可以看出它有4个方法(当然,除非我错了):它可以在创建新实例时初始化一个默认的空bean数组它可以计算它有多少个bean它可以读取它有多少个bean(通过attr_accessor)它可以向空数组写入(或添加)更多bean(也通过attr_accessor)但是,当我询问类本身它有哪些实例方法时,我没有看到默认

随机推荐