当您需要/拥有作为本机java数组的数据时,carrays.i与arrays\u java.i的SWIG效率
我很好奇swig中关于swig/java中处理数组的两种基本方法的效率的说法。特别是,我想知道如果您最终需要向本机java数组进行复制或从本机java数组进行复制,那么carrays.I方法是否真的更有效?例如,假设我要调用一个C func void populate(int x[]),然后我需要将结果传递给一个采用本机Java int[]的Java func。要以carrays的方式进行,我需要:当您需要/拥有作为本机java数组的数据时,carrays.i与arrays\u java.i的SWIG效率,java,swig,Java,Swig,我很好奇swig中关于swig/java中处理数组的两种基本方法的效率的说法。特别是,我想知道如果您最终需要向本机java数组进行复制或从本机java数组进行复制,那么carrays.I方法是否真的更有效?例如,假设我要调用一个C func void populate(int x[]),然后我需要将结果传递给一个采用本机Java int[]的Java func。要以carrays的方式进行,我需要: %include "carrays.i" %array_class(int, intArray)
%include "carrays.i"
%array_class(int, intArray);
intArray array = new intArray(10000000);
populate(array);
然后复制到本机java阵列:
int[] nativeArray = new int[10000000];
for(int i = 0; i < 10000000; ++i)
{
nativeArray[i] = array.getitem(i);
}
这真的比你想象的更有效率吗
%include "arrays_java.i"
int[] nativeArray = new int[10000000];
populate(nativeArray);
f(nativeArray);
因为在前一种情况下,您无论如何都必须进行复制?假设您使用的是carrays。那么,您也不是在Java数组之间来回复制-您希望使用carrays。我在任何地方键入,而不是那样 仍然有两种类型的开销需要度量——JNI调用会招致某种惩罚,而复制另一种惩罚。使用carray.i,后者被保持在较低的水平,以获得您正确识别的更多JNI调用的价格。另外,对
GetArrayElements
的调用也可能会根据JVM引入一个副本
然而,可能令人惊讶的是,arrays_java.i的实现产生的副本比您预期的要多,例如,类型映射使用的SWIG_JavaArrayIn函数包含以下内容:
传递指向从VM获得的Java数组的指针(该数组可能是副本,也可能不是副本,您可以使用可选的第三个参数检查GetIntArrayElements
,该参数是一个布尔值,指示JVM是否在进程中创建了副本)
这些类型映射以“原样”的形式传递Java数组,然后从JVM获取一个指针以在C函数中使用。如果函数成功,则调用releaseintarayelements
,第三个参数为0-这确保Java中的任何修改也可见。如果调用不成功,则将使用JNI\u ABORT
调用该函数,在返回的指针是副本的情况下,该函数不会做出任何可见的更改
我们可以称之为:
public class run {
public static void main(String[] argv) {
System.loadLibrary("test");
int[] arr = new int[100000];
test.populate(arr);
// Only print 40 to avoid spamming my screen!
for (int i = 0; i < 40; ++i) {
System.out.println(arr[i]);
}
}
}
公共类运行{
公共静态void main(字符串[]argv){
系统加载库(“测试”);
int[]arr=新int[100000];
测试。填充(arr);
//只打印40,以避免垃圾邮件我的屏幕!
对于(int i=0;i<40;++i){
系统输出打印项数(arr[i]);
}
}
}
它可能有0个副本,但只能在Java中的类型与C中的相应类型完全匹配的情况下使用。Hmm,在arrays_Java.i版本中可能有2个隐式副本,这仍然会降低效率?谢谢。我最关心的是将字节数组传递到C/C++中,它看起来像各种类型的char*字节类型映射。我类似于上面为int[]编写的高效类型映射。
for (i=0; i<sz; i++)
JAVA_TYPEMAP_ARRAY_ELEMENT_ASSIGN(CTYPE)
for (i=0; i<sz; i++)
arr[i] = (JNITYPE)result[i];
%module test
%typemap(jtype) int arr[ANY] "int[]"
%typemap(jstype) int arr[ANY] "int[]"
%typemap(jni) int arr[ANY] "jintArray"
%typemap(javain) int arr[ANY] "$javainput"
%typemap(in) int arr[ANY] {
// check the size is compatible here also
$1 = JCALL2(GetIntArrayElements, jenv, $input, 0);
}
%typemap(freearg) int arr[ANY] {
if ($1) {
JCALL3(ReleaseIntArrayElements, jenv, $input, $1, JNI_ABORT);
}
}
%typemap(argout) int arr[ANY] {
JCALL3(ReleaseIntArrayElements, jenv, $input, $1, 0);
$1 = NULL;
}
%inline %{
void populate(int arr[100000]) {
for (unsigned i = 0; i < 100000; ++i) {
arr[i] = -i;
}
}
%}
public class run {
public static void main(String[] argv) {
System.loadLibrary("test");
int[] arr = new int[100000];
test.populate(arr);
// Only print 40 to avoid spamming my screen!
for (int i = 0; i < 40; ++i) {
System.out.println(arr[i]);
}
}
}