Bug 57577 - Instantiating Java object from C# many times is very slow
Summary: Instantiating Java object from C# many times is very slow
Status: RESOLVED ANSWERED
Alias: None
Product: Android
Classification: Xamarin
Component: Bindings ()
Version: 7.3 (15.2)
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Atsushi Eno
URL:
Depends on:
Blocks:
 
Reported: 2017-06-17 16:44 UTC by James Ko
Modified: 2017-06-23 18:38 UTC (History)
2 users (show)

Tags: bb
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED ANSWERED

Description James Ko 2017-06-17 16:44:45 UTC
Hi, I posted this at https://forums.xamarin.com/discussion/97915/instantiating-java-object-from-c-many-times-is-very-slow/p1?new=1 recently, but I figured Bugzilla would be more appropriate. I'll paste my original post here so you don't have to follow the link.

===

Hi,

I'm working on a Xamarin.Android app that offers syntax highlighting for code. I am calling `new ForegroundColorSpan(color)` very frequently in a loop, and this is the only piece of Java code that I call from C# while syntax highlighting. For large files with thousands of lines of code, the app takes an extremely long time to load. I have done some random sampling via pausing the debugger repeatedly while the files are loading, and the debugger keeps stopping on the above line. [This](https://github.com/android/platform_frameworks_base/blob/master/core/java/android/text/style/ForegroundColorSpan.java#L30) is all there is to the implementation of `ForegroundColorSpan(int)`, so I strongly suspect it has to do with Java interop.

Is there anyway to work around this? I have tried caching ForegroundColorSpans for the same color via a Dictionary, but due to the way the Spannable APIs are designed one cannot call SpannableString.setSpan with the same span object for a different range.

Thanks.
Comment 1 James Ko 2017-06-17 20:33:52 UTC
Hello, so I looked a bit further into the issue by manually implementing Java bindings after reading the "Working with JNI" document on the Xamarin website. I wrote this

namespace Repository.Internal.EditorServices.Highlighting
{
    [Register("android/text/style/ForegroundColorSpan", DoNotGenerateAcw = true)]
    internal class FastForegroundColorSpan : JavaObject
    {
        private static readonly IntPtr class_ref = JNIEnv.FindClass("android/text/style/ForegroundColorSpan");

        private static IntPtr id_ctor_I;

        [Register(".ctor", "(I)V", "")]
        public unsafe FastForegroundColorSpan(int color)
            : base(IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
        {
            if (Handle != IntPtr.Zero)
            {
                return;
            }

            if (id_ctor_I == IntPtr.Zero)
            {
                id_ctor_I = JNIEnv.GetMethodID(class_ref, "<init>", "(I)V");
            }

            var args = stackalloc JValue[1];
            args[0] = new JValue(color);
            var handle = JNIEnv.NewObject(class_ref, id_ctor_I, args);
            SetHandle(handle, JniHandleOwnership.TransferLocalRef);
        }
    }
}

Now when I pause the debugger randomly, it's always on SetHandle(). So that appears to be the bottleneck.

You can view the source code of my app here: https://github.com/jamesqo/Repository/blob/1ac7fb86b80199e4aa3e02b980afa25a4bc9eb78/Repository/Internal/EditorServices/Highlighting/FastForegroundColorSpan.cs#L35
Comment 2 James Ko 2017-06-17 21:20:12 UTC
Link to SO question where I posted more information: https://stackoverflow.com/q/44603453/4077294
Comment 3 Jon Douglas [MSFT] 2017-06-23 15:30:27 UTC
Hi James,

Is this still an issue for you? It seems that you're aware of the difference between GREF limits on the emulator vs a physical device and you resolved it on your end. Thus I'm marking this bug as RESOLVED ANSWERED for the time being. If it's still an issue, please change the status to REOPENED or comment on this thread and I will do it for you:

https://stackoverflow.com/questions/44603453/how-to-workaround-slowness-of-xamarin-android-java-interop#comment76229397_44621666