Thursday, January 02, 2014

Question: Mono.Android performance: C# -> JNI wrapper -> native lib vs. C# -> Managed wrapper -> native?

I have currently ported a Java app to Mono.Android. The Java app uses a native library.

The full walk through can be read here: WebRTC app - C# / Xamarin - (C# - JNI - C/C++) - Summary and GitHub repository


Basically I have some Java code that looks like this

public native int GetVideoEngine();
Initially in my C# equivalent app I tried to use DllImport
[DllImport("libwebrtc-video-demo-jni.so")]
public static extern int Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_GetVideoEngine();
(which did not work), then I ended up wrapping the jars as Java Binding Libraries which in turn JNI'ed the needed classes, so I instead could call the generated JNI wrappers
static Delegate cb_GetVideoEngine;
#pragma warning disable 0169
static Delegate GetGetVideoEngineHandler ()
{
    if (cb_GetVideoEngine == null)
        cb_GetVideoEngine = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, int>) n_GetVideoEngine);
    return cb_GetVideoEngine;
}

static int n_GetVideoEngine (IntPtr jnienv, IntPtr native__this)
{
    global::Org.Webrtc.Videoengineapp.ViEAndroidJavaAPI __this = global::Java.Lang.Object.GetObject<global::Org.Webrtc.Videoengineapp.ViEAndroidJavaAPI> (jnienv, native__this, JniHandleOwnership.DoNotTransfer);
    return __this.VideoEngine;
}
#pragma warning restore 0169

static IntPtr id_GetVideoEngine;
public virtual int VideoEngine {
    // Metadata.xml XPath method reference: path="/api/package[@name='org.webrtc.videoengineapp']/class[@name='ViEAndroidJavaAPI']/method[@name='GetVideoEngine' and count(parameter)=0]"
    [Register ("GetVideoEngine", "()I", "GetGetVideoEngineHandler")]
    get {
        if (id_GetVideoEngine == IntPtr.Zero)
            id_GetVideoEngine = JNIEnv.GetMethodID (class_ref, "GetVideoEngine", "()I");

        if (GetType () == ThresholdType)
            return JNIEnv.CallIntMethod  (Handle, id_GetVideoEngine);
        else
            return JNIEnv.CallNonvirtualIntMethod  (Handle, ThresholdClass, id_GetVideoEngine);
    }
}

My question is related to performance:

How much slower is the C# -> JavaBindingLibrary (JAVA/JNI) -> C/C++ JNI Wrapper -> C native library than if I did unwrapped the C/C++ JNI Wrapper and rewrapped it with something like mono / cxxi or similar direct managed or manually wrote a direct callable wrapper?

No comments: