问题描述
到目前为止,我已经让Javonet致力于调用.net dll.创建广告代码就像创建广告一样简单.
但是,就我而言,我有一个循环运行大约一千万次,并且在该循环中,我正在通过Javonet调用dll方法.我的问题是:由于我似乎将方法名称作为字符串传递给Javonet(基于javonet的处理方式),因此我假设Javonet使用某种反射来找到相应的dll方法...但是不会.这会很慢(在一千万次循环中),尤其是因为我们已经为javonet注册了大约十二个不同的dll(或者比jni4net和jnbridge等解决方案要慢,它们似乎会生成实际的代理,使我可以在其中引用我的Java代码中dll方法自己命名,而没有将方法名称作为字符串传递?)
此外,Javonet是否聪明"到足以将整个数组(原语)复制到"Java VM的内存/堆栈"中,以便当我尝试访问(非常大的约2GB数组)中的每个元素时,不会尝试对每个元素访问都进行JNI调用吗?
最后,总的来说,在上述情况下,有没有理论上(或观察到的)理由使Javonet比jni4net或jnbridgePro更快(或更慢)(大小为1000万的循环和包含大约2GB的基本数组)原始浮点数)?
感谢您的良好反馈!
Javonet不会对您的1000万个调用中的每个调用进行反射调用,我们会第一次扫描类型,但所有后续调用都将对指向目标方法的固定指针进行.
附带说明: 当前在Java开发人员的Javonet中,您的字符串方法名称仍传递给.NET端(即使在以后的调用中也不使用),这会影响性能,但我们已经对其进行了优化在.NET开发人员的Javonet中.请通过电子邮件与Javonet支持人员联系,以获取具有该产品Java版本所包含的优化功能的非正式版本.
如果您检索基元数组,则Javonet将在一次调用中返回整个数组,因此您可以将其作为纯Java数组进一步使用,而无需任何返回.NET的调用. Javonet还能够返回混合数组,其中某些项是基元(转换为Java类型),而有些则是类,它们在最终Java Object [] 中显示为 NObject 实例./p>
有意地,我们希望使用JIT生成包装器和反射样式的API,而不是预先生成的包装器,以提供使用Javonet的最大灵活性.因此,开发人员可以自行决定如何使用目标库,如何优化代码以最小化跨边界调用.此外,无需安装任何工具或扩展程序或运行任何应用程序即可通过Javonet使用.NET DLL.我们的目标是确保您在前5分钟内下载单个文件并使用Java中的任何.NET代码.
总结Javonet实际上是在执行过程中动态地构建了固定的包装器.为了提高语法的可用性,您可以使用强类型的接口包装您的类,并通过Javonet API在内部路由调用.首次通话后,您的路由将得到优化,并且平均每次通话应执行九百万分之一秒.如果您有更高的需求,请告诉我们,我们很高兴满足您的要求!
示例包装器可能如下所示:
class Car {
private NObject handle;
public Car() throws JavonetException {
handle = Javonet.New(Car.class.getName());
}
public void increaseSpeed(int newSpeed) {
handle.invoke("startEngine", newSpeed);
}
public void addPassenger(Passenger person) {
handle.invoke("addPassenger", person);
}
}
class Passenger {
private NObject handle;
public Passenger(String name) {
handle = Javonet.New(Passenger.class.getName(),name);
}
}
请注意私有的句柄"字段.如果您呼叫 Javonet.setUsePrivateHandleField(布尔值) 激活Javonet.当您将带有私有句柄字段Javonet的此类的实例作为任何.NET方法的参数传递时,Javonet将使用适当的.NET实例.
So far, I've gotten Javonet to work to calling a .net dll. It was as easy as advertised to create the javonet code.
However, in my case, I have a loop that runs approx 10 million times, and within that loop, I'm calling a dll method via Javonet. My question is: since I seem to pass the method name as a String to Javonet (based on javonet's way of doing things), I'm assuming that Javonet uses some sort of reflection to find the corresponding dll method...but wouldn't that be slow (when in a 10 million loop) especially since there are about a dozen different dlls that we've registered for javonet (or slower than solutions such as jni4net and jnbridge that seem to generate actual proxies which allow me to reference in my java code the dll method names themselves without passing the method name as a String?)
Also, is Javonet "smart" enough to copy the whole array (of primitives) into the "Java VM's memory/stack" so that when I try to access every element in the (very large, approx 2GB array) it doesn't try to do a JNI call for every element access?
Lastly, in general, is there any theoretical (or observed) reason why Javonet would be (substantively) faster/slower than jni4net or jnbridgePro in my scenario above (a loop of size 10 million and arrays of primitives that contain approx 2GB of primitive floats)?
Thanks for your good feedback!
Javonet does not make a reflection calls for each of your 10 mln calls, we do scan the types first time but all subsequent calls are done to fixed pointers to the target method.
Side note: Currently in Javonet for Java developers your string method name is still passed to .NET side (even not used in further calls) what can affect performance but we already optimized that in Javonet for .NET developers. Please contact Javonet support via email to get unofficial build with that optimization included in Java version of the product.
If you retrieve arrays of primitives Javonet will return entire array in one call so you can use it further as pure Java array without any calls back to .NET side. Javonet is also able to return mixed arrays where some items are primitives (translated to java types) and some are classes which appear as NObject instances in final Java Object[].
Intentionally we prefer JIT generation of wrappers and our reflection style API over the pre-generated wrappers to give maximum flexibility of using Javonet. So developers can decide by themselves how they use target libraries, how they optimize code to minimize cross-boundaries calls. Moreover there are no needs to install any tools or extension or run any application to use .NET DLL through Javonet. That's our goal to make sure you download single file and use any .NET code from Java in first 5 minutes.
Summarizing Javonet in fact builds the fixed wrapper on the fly during the execution. For syntax usability you can wrap your class with strongly typed interfaces and route the calls internally through Javonet API. After first call your route will get optimized and should perform averaging nine millionth of a second per call. Let us know if you have higher needs we would be pleased to address your requirements!
Sample wrapper could look like this:
class Car {
private NObject handle;
public Car() throws JavonetException {
handle = Javonet.New(Car.class.getName());
}
public void increaseSpeed(int newSpeed) {
handle.invoke("startEngine", newSpeed);
}
public void addPassenger(Passenger person) {
handle.invoke("addPassenger", person);
}
}
class Passenger {
private NObject handle;
public Passenger(String name) {
handle = Javonet.New(Passenger.class.getName(),name);
}
}
Please notice the private "handle" field. If you call Javonet.setUsePrivateHandleField(bool value) before activating Javonet. When you will pass instance of such class with private handle field Javonet as argument to any .NET method Javonet will use proper .NET instance.
这篇关于Javonet的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!