Most efficient way to add data to Xamarin.Android chart


#1

We’re trying to load data every second (or quicker) from a .net array into a SimpleDataAdapter and we’re running out of GREFs.  I want to make sure we’re doing it the most efficient way.  I saw this thread about the issue two years ago but wanted to see if anything has changed since then.  We’re basically loading a few thousand datapoints every second (at the least), and using a double for the x and y axis.  We managed to widdle it down from 10s of thousands by taking every nth record to display and redrawing when they zoom in/out, but it’s still running out of GREFs trying to add to the adapter.

We’re also using AddAll, which seems like the most efficient way vs Add and manually updating, but maybe that’s not true?

Lastly, I saw the new release for iOS efficiency this morning.  Is anything like that planned for Android?  It seems like that would help (and we’re not having any issues with iOS…)

Thanks,
Jamie


Android Chart (Xamarin edition): Out of GREF
#2

Hi Jamie,

I’m sorry to hear you’re coming up against this problem.

Firstly, even when using the Java version of shinobicharts, it will be more efficient to use the AddAll method rather than the Add method if you’re adding a large number of data points when using the SimpleDataAdapter. This is because the SimpleDataAdapter will fire an update after every Add method, whereas only one update is fired at the end of the AddAll method. One alternative option is to subclass (the abstract) DataAdapter and control the firing of the update yourself.

Obviously here you are already using the AddAll method so from that respect it sounds like you’re being as efficient as possible.

The main issue here then is one that ultimately is a consequence of using Xamarin.Android. Java libraries are bound using the JNI and there is an inherent cost associated with crossing this boundary. While there are things that can be done to improve the situation there will always be some cost and so this has to be weighed against the various other gains you get from using Xamarin.

To answer your question, there hasn’t been anything that has changed in our library since the thread you linked to (with respect to Xamarin specific DataAdapters… obviously many other things have changed!). We prioritise development based on customer feedback but aside from that thread we haven’t had any further requests for Xamarin specific DataAdapter improvements and as such it simply hasn’t been a high priority item in our backlog. I will of course make note of your request and will continue to monitor this issue’s popularity but I have to be honest and say that it is unlikely to be completed any time soon. I realise this isn’t the answer you hoped for but it wouldn’t be fair for us to promise things we can’t deliver.

In the thread you linked to you will have seen the suggestions that were made by the guys at Xamarin. Specifically, have you tried disposing of your DataPoints as soon as they have been added? Note, this only works as long as you are using the DataPoint class and are not subclassing it. It’s not something I’ve tried myself but it could be worth trying out a few things. For example, something like:

using (var point = new DataPoint (1.0, 100.0))

    adapter.Add (point);

This should mean the DataPoint’s GREF is freed immediately – you would need to think about the firing of updates from the SimpleDataAdapter with this method so subclassing DataAdapter instead and handling the firing yourself may be the way to go (even if is just exposing a public method that you can explicitly call after you’ve loaded your points to do the update).

Also, while you’re likely using .NET doubles for your datapoint values, I’m guessing this will mean a Java.Lang.Double will be created on the .NET side meaning more GREFs. So, using the same principle you might be able to reduce the number of GREFs by doing the following:

using (Java.Lang.Double xValue = Java.Lang.Double.ValueOf(x)) {

    using (Java.Lang.Double yValue = Java.Lang.Double.ValueOf(y)) {

        using (DataPoint dataPoint = new DataPoint(xValue, yValue)) {

            dataAdapter.Add(dataPoint);

        }

    }

}

You could probably structure that much more nicely (maybe using the Dispose() method on the objects) but hopefully you get the idea!

You may of course be already doing this but it should hopefully reduce the number of GREFs you see. It won’t however address the time it takes to execute – this is down to the JNI invocation overhead as was explained in that original thread and at present we have no immediate plans to address this.

As for your last question, I’m assuming you’re referring to the ‘Advanced Charting Kit’. While we’re not quite at the same point as the iOS team we are actively developing an Android version as we speak!

I’m not entirely convinced that it will particularly help the problem you’re facing here although what it will give you, for example, is an out-of-the-box solution to the sampling you have employed depending on zoom level. I would also imagine the smoothing behaviour wouldn’t be affected by the GREFs problem as the extra “datapoints” needed to smooth the line series will be done on the Java side.

I hope that all makes sense.

Kind regards,

Patrick


#3

I’m glad I ran across this! This problem has bedeviled my company for a couple of years.

I used the “Using…” pattern to avoid generating GREFs for large data sets (tonight I tested 92,000 points, for instance).

This has created crashes ever since we launched out Android app.

i couldn’t use the AddAll approach, because the objects can’t be freed until the collection is passed across. So they build up anyway and the magic limit is reached.

I wish Shinobi was a little more Xamarin-focused. We’ve wanted and been asking for a Forms control for years. Having two separate products (iOS and Android) for charting, with radically different APIs is a pain. We prefer one app, one team, multiple platforms.


#4

Hi jbeans.

From your post I am unclear whether you are still experiencing the crashes, or are you saying your use of the ‘using’ pattern has resolved the issue? If you are still experiencing crashes, please do get in touch with us directly at info@shinobicontrols.com and we will do our best to help you.

I do appreciate your feedback regarding not providing a Forms control and I will certainly take note of it. We do base our future development on customer demand and at present, demand for new features, such as those included within our Advanced Charting Kit is much greater than that for Xamarin improvements.

We have also been thinking about providing Xamarin specific DataAdapters for some time and indeed have this in our backlog. It is simply a matter of demand and I certainly will add your interest in this. We periodically evaluate and prioritise these backlog items and the more interest we have in a feature, the more likely it is to be added.

I do appreciate what you are saying about us having two separate products for charting. This is in part a consequence of us starting the Android development some time after that of iOS charts and in part down to the number of users who simply do not use Xamarin. As for the API differences, in some cases they arose from lessons learnt during the iOS development, in others it was to be a little more ‘Java-y’.

Again, thanks for the feedback and I assure you it has been noted and will be considered in the future.

Thanks,

Kai.