[英]JNA Native.setXXX() slow
不确定这是否是问的正确地方。 我在 YourKit(但任何其他分析器都可以)中注意到 Native.setShort 的巨大贡献,就我而言。 这会在 Structure 中设置字段以填充 jna 库调用参数。 SetShort 在 jna lib 代理调用下大约 10 个级别被调用。 对windows 的kernel32.dll 的实际函数调用根本没有出现在采样中。 返回值时也没有任何 Structure.read 活动。
现在,我查看了 this 和其他原始值 setter 的作用:它们获取参数的地址并通过 memcpy 或 bcopy 将 sizeof(argument) 字节移动到目标地址,可能被 try/catch 宏包围。 为什么完成? 为什么不只是这样的:
*((short*) target) = value
这会更有效还是 try/catch 在这里很重要? 周围的 PSTART/PEND 宏似乎并不总是生成 try/catch。 这是最新的 JNA 从 git 中抓取 4.2.0。
更新:看起来这是分析器对我开了个恶作剧。 今天,我看到浪费的时间更均匀地分布在来自和到实际本机调用的其他调用堆栈级别。
我的解决方案是使用 JNA 直接映射:在 OS API 之上的我自己的 DLL 中添加另一个函数,该函数采用原始指针而不是Structure.ByReference
来返回值。 为每个返回参数使用一个元素的原始数组调用此函数需要 370 ns 与 1500 ns(不包括new Structure.ByReference()
)。
所以,最后,Native.setXXX() 方法和围绕 JNA 方法调用的所有胶水代码确实很慢。 但是 JNA 直接映射做到了。 我从未测试过实际的 JNI 调用,因此无法在这里比较时间。
在 *nix 系统上, PSTART
/ PEND
执行setjmp
/ longjmp
以捕获一系列内存故障(但仅限于Native.setProtected(true)
)。 在 Windows 上,它使用结构化异常处理(基本上是try
/ catch
)来做同样的事情,默认情况下是打开的。
即使启用,与 JNI 转换本身的开销(从 Java 到 C 或反之亦然)相比,它们也不太可能增加太多开销。
通常,将Structure
传递给本机代码的效率并不高,因为自动写入和读取在很大程度上依赖于将 Java 字段复制到本机内存的反射。 不过,在大多数情况下,这并不重要。
对于发现瓶颈的少数情况,您可能希望使用 JNA 的直接映射并将自己限制在原始参数上。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.