Poor man’s performance profiling

If you have been doing development with Xamarin on Android you have probably noticed the total absence of any profiler, there is not even a decent method to get the high resolution time. Sure, there is Environment.TickCount but the resolution is at best in milliseconds. Pretty useless for performance profiling.

Rarely people use performance profilers on the desktop. Mostly because their applications don’t have complicated stuff and the modern CPUs are hiding most of the non performing code. However mobile devices are far more delicate and have less CPU power, less RAM, less resources in general. Thus slow code is much more notable and visible to end users. There is no better way to profile your code with a performance profiler. Just take a look at RedGate’s ANTS Performance profiler. Unfortunately there are no such tools for Xamarin Android platform even though mobile code should be really optimized.

I present  my solution for getting some useable metrics from your code (the code you have sources for). The code I’ve written was used for MvvmCross performance profiling hence it slightly relies on it (logging, IoC) however it can be easily made standalone if necessary.

Getting high resolution time

Java has java.lang.System.nanoTime() method that returns the highest resolution time available on Android. Xamarin doesn’t provide it through .net, you have to write a wrapper by yourself using java reflection.

public static class JavaLangSystem
{
    static IntPtr class_ref;
    static IntPtr id_nanoTime;
    public readonly static long Avg;

    static JavaLangSystem()
    {
        class_ref = JNIEnv.FindClass("java/lang/System");
        id_nanoTime = JNIEnv.GetStaticMethodID(class_ref, "nanoTime", "()J");

        for (int i = 0; i < 10; i++)
        {
            NanoTime();
        }

        long start = NanoTime();
        for (int i = 0; i < 1000; i++)
        {
            NanoTime();
        }
        Avg = (NanoTime() - start) / 1000;
MvxTrace.TaggedTrace("metrics", "Avg NanoTime reflection is {0}", Avg); } [Register("nanoTime", "()J", "")] public static long NanoTime() { return JNIEnv.CallStaticLongMethod(class_ref, id_nanoTime); } }

Note that I do some calibration in static constructor because of reflection the call to nanoTime() itself consumes some time. I store the average call time into a static variable Avg that I'll later use.

Accessing high resolution timer through IoC

First part is to create an interface

public interface IHighResolution
{
    long Ticks { get; }
    long Avg { get; }
}

then implement it

public class HighResolution: IHighResolution
{

    #region IHighResolution Members

    public long Ticks
    {
        get { return JavaLangSystem.NanoTime(); }
    }

    public long Avg
    {
        get { return JavaLangSystem.Avg; }
    }

    #endregion
}

and finally register it to IoC provider.

protected override IMvxApplication CreateApp()
{
    Mvx.RegisterType<IHighResolution, HighResolution>();
    return new App();
}

I register it in MvxAndroidSetup derived class (MvvmCross initialization) but if you are not using MvvmCross feel free to register it with IoC provider of your choice on some other initialization place.

This separation comes specially handy if you are to measure PCL assemblies where nanoTime() isn’t accessible.

 

Define class that will store a single measurement

[DebuggerDisplay("{Name} in {Ticks}")]
public class PerfMeasurement
{
    public string Name { get; set; }
    public List<PerfMeasurement> Children;
    public long Ticks { get; set; }

    public int AllChildren
    {
        get
        {
            if (Children == null || Children.Count == 0)
                return 0;
            else
            {
                int sum =0;
                foreach (PerfMeasurement m in Children)
                {
                    sum += 1 + m.AllChildren;
                }
                return sum;
            }
        }
    }
}

There are two interesting features here. First is Children field which holds nested measurements. And the other is AllChildren property that recursively counts all children.

The main measurement class

public static class Metrics
{
    private static readonly IHighResolution highresolution;
    private static readonly long twoAvg;
    
    public static List<PerfMeasurement> RootData { get; private set; }
    private static Stack<PerfMeasurement> stack;
    //         private static int counter;
    
    static Metrics()
    {
        RootData = new List<PerfMeasurement>(100000);
        stack = new Stack<PerfMeasurement>();
        highresolution = Mvx.Resolve<IHighResolution>();
        twoAvg = highresolution.Avg * 2;
    }
    
    public static PerfMeasurement Push(string name)
    {
        PerfMeasurement head;
        if (stack.Count == 0)
        {
            head = new PerfMeasurement { Name = name };
            RootData.Add(head);
        }
        else
        {
            PerfMeasurement previous = stack.Peek();
            head = new PerfMeasurement { Name = name };
            if (previous.Children == null)
                previous.Children = new List<PerfMeasurement>();
            previous.Children.Add(head);
        }
        stack.Push(head);
        return head;
    }
    
    public static void Pull()
    {
        stack.Pop();
        if (stack.Count == 0)
        {
            PerfMeasurement m = RootData[RootData.Count - 1];
            OffsetParents(m);
            Print(m);
        }
    }
    
    private static void OffsetParents(PerfMeasurement m)
    {
        m.Ticks -= m.AllChildren * twoAvg;
        if (m.Children != null)
        {
            foreach (PerfMeasurement child in m.Children)
                OffsetParents(child);
        }
    }
    
    public static void Print(PerfMeasurement metric)
    {
        StringBuilder sb = new StringBuilder();
        Print(metric, sb, 0);
        MvxTrace.TaggedTrace("metrics", sb.ToString());
    }
    
    public static void Print(PerfMeasurement metric, StringBuilder sb, int depth)
    {
        string prepend = new string(' ', depth * 4);
        sb.AppendLine(string.Format("{0}{1} took {2:#,##0}", prepend, metric.Name, metric.Ticks));
        if (metric.Children != null && metric.Children.Count > 0)
        {
            foreach (PerfMeasurement child in metric.Children)
            Print(child, sb, depth + 1);
        }
    }
}

This class acts like a Stack for measurement items defined in earlier one. When item at the root level is pulled it outputs the results of the whole hierarchy linked to it into the (MvvmCross) logging mechanism (Print methods). But before doing that it recursively subtracts the nanoTime() invocation of all children (OffsetParents - for each children it assumes nanoTime() took two average invocations – hence the static field twoAvg).

That’s all we need. However there is one step that will make measurement a bit easier and more clean.

 

Making it easier to use Metrics with a helper class

public class MeasurePerf : IDisposable
{
    private static readonly IHighResolution highresolution;

    private long start;
    private PerfMeasurement m;

    static MeasurePerf()
    {
        highresolution = Mvx.Resolve<IHighResolution>();
    }

    public MeasurePerf(string name)
    {
        m = Metrics.Push(name);
        this.start = highresolution.Ticks;
        
    }

    public void Dispose()
    {
        m.Ticks += highresolution.Ticks - start - highresolution.Avg;
        Metrics.Pull();
    }
}

This class is intended as a wrapper around measured code using using keyword. Measurement looks like:

using (new MeasurePerf("Your comment here"))
{
    // your code here
    // nesting measuring is perfectly fine
}

Here is a sample output I’ve been looking at:

profiler_results

I highlighted the root item. All items are showing their total time (children included). Note the negative numbers. That happens because this kind of measurement isn’t accurate at all (remember, I am subtracting twoAvgs). However it gives you at least some insight of what code is slow and which child is guilty.

So, that’s it. Until Xamarin gives us profilers there is no better way AFAIK. Unfortunately. There is one thing you can do, though. You can tell Xamarin that we need profilers. Perhaps through my uservoice suggestion.

A week of impressions of developing for Android using Xamarin & MvvmCross

Occasionally I watch road bicycling and it happens that I started following Vuelta 2013. Of course I downloaded the official application for Android as well - to keep an eye on standings. The poor quality of the Android application bothered me a bit. Both the lack of data and poor UI. Most notably I really found it hard to see where my favorite bicyclists are standing.

This triggered a well known feeling in me - I have to create my own Android application instead. For quite some time I was eying Android development but so far I didn't have a proper motivation.Armed with Xamarin and MvvmCross I dived in. I had almost no experience with Android OS development, very little of Xamarin and none of MvvmCross. The goal was to create a MVVM based application that could leverage the common code along different mobile platforms though the current state is Android only application. I could create a version for iOS and Windows Phone 8 as well, I guess, but I don't have a Mac (required to build for iOS) nor I want to loose a ton of time to enable Windows Phone development environment for a free application (which is a shame because WP8 development doesn't look bad at all). Perhaps sometime.

The application itself is available for free through Google Play. Go, get it, while it is still actual.

About Xamarin

What they have done is simply amazing. Porting Mono (.net) stack to mobile platforms that is. Including the latest crazy useful async/await.This gives a .net developer an option to provide common code base for Windows RT, desktop Windows, Windows Phone, Android and iOS and to unleash the .net on platforms MS didn't want you to. The community is there. But it comes with some quirks. Here are some major ones I found while developing with Visual Studio 2012:

  • debugger is often slow. Sometimes it takes quite a lot of tenths of seconds to be able to inspect variables at a breakpoint
  • async/await debugger breakpoints stop at random lines of code and often "Step Over" or "Step Into" means "Continue running"
  • Portable Class Library support is still a problem (most notably, VS Android projects can't reference PCL assemblies while Xamarin IDE intellisense goes beserk on PCLs)
  • no profilers available (performance, memory) for Android. These are insanely important for mobile devices. Vote here.
  • price for Indie developers (small shops) might be high

I am not exactly sure whether some of these problems might be attributed to VS or Xamarin integration. Anyway, none of these is a showstopper and I am sure they'll be addressed.

About MvvmCross

This framework is an excellent open source MVVM starting point for cross platform .net mobile development. @slodge. the author, has done and is still doing an insane job. Not just by creating the framework but he is all over the Internet answering questions and writing (well, mostly recording) documentation and samples. That said there are some problems with MvvmCross:

  • huge framework, takes time to grasp
  • I miss better fundamentals description (i.e how DataContext is transferred to children)
  • sometimes slow (i.e. startup time, ListView bindings). NOTE: since there is no performance profiler available I couldn't exactly determine why it acts slowly sometimes. Could be Xamarin, could be MvvmCross or Android or my code.
  • some error messages could be better (i.e. suggesting you a solution instead of just reporting errors)

But hey, it is open source and I plan to contribute if time permits.

About Android

It is not hard to learn the basics but it has plenty of small issues and traps one has to be aware of. The fragmentation doesn't help either nor does java stack but overall it isn't that big of an issue.

Then there are Intel Android x86 images which are used if you want to run the emulator. (Forget about ARM ones due to the slowness). Intel Android x86 v17 image has a quirk that logs messages like nuts making log window pretty much useless. Then there is the v18 image that fixed overlogging issue but introduced a new one. It'd throw "can't resolve host" when using HttpClient 99% of the time. This issue might be attributed to Xamarin though as its browser doesn't exhibit same problems.

Google Play store publishing

Straightforward, no issues. Wait, there is a potential problem. If you want to publish an app on Google Play store you have to comply to US laws, most notably they warn you of using encryption. I wonder why (rhetorical).

So, these are my impressions, after a week of development. Note that I mostly listed problems I've encountered not described the (bright points of) products in details.

Feel free to feedback me.

How to compile MvvmCross v3 sources

As you well know, or you might not, MvvmCross is a cross platform MVVM framework supporting many platforms, such as Android and iOS (both through Xamarin), WPF, WinRT, WP7. Feature worth drooling.

Now, AFAIK there are two versions available. v2 (aka vNext) which is supposedly stable and v3 which is work in progress but holds many improvements. Here is how to get v3 sources compiled for Android (I didn’t test others) in case you run into problems like me.

  1. head to Github repository for v3 branch (optionally)
  2. use git clone –b v3 git://github.com/slodge/MvvmCross.git do fetch sources
  3. open MvvmCross_All.sln solution (using Visual Studio 2012) which references all projects for all platforms. If you don’t have Touch support (or others) Visual Studio will let you know. You can safely ignore those warnings.
  4. build solution. If it does consider yourself lucky, otherwise continue reading.
  5. If you get something like

Error 172 Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly 'Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'. Perhaps it doesn't exist in the Mono for Android profile?
File name: 'Newtonsoft.Json.dll'

then there is a problem with build process. My guess is that it happens because portable class libraries, which Newtonsoft.Json.dll is, aren’t officially supported by Xamarin. Yet.

The workaround is to get Newtonsoft.Json sources (use PCL csproj version), include the project into solution and replace the reference in Plugins\Cirrious\Json\Cirrious.MvvmCross.Plugins.Json project with the Newtonsof.Json project itself.

Now you can run samples, at least I did – tested with Samples\Tutorial\Tutorial.UI.Droid.

There is another build error you might encounter (in general for Xamarin.Android). Sometimes the build process yields a ton of senseless errors (can’t find classes, interfaces, etc.) even though the code should compile. Try building again – most of the times it builds without errors the second time.

If you are interested into MvvmCross project make sure you read Stuart’s blog (creator of MvvmCross).

I have to test it a bit now, so more blog posts on the topic might follow.

Have fun with MVVM everywhere.

Two dimensional ScrollView for MonoDroid

There is no two dimensional scroll view for Android out of the box – the one that lets user scroll in both horizonal and vertical direction. There are either horizontal (HorizontalScrollView) or vertical (ScrollView) but not both. After some Googling around I’ve found that devs were mosty experimenting with combining HorizontalScrollView within ScrollView. This approach didn’t work for me and even if it did it has some drawbacks (such as scrolling is rectriected by one of the two directions at the same time).

At this point I was considering creating my own proper ScrollView from scratch but luckily I’ve stumbled across an implementation of the same idea by Matt Clark. The only problem was that I am on Mono For Android and Matt’s implementation is in pure java. Plus I didn’t have a clue whether his solution actually worked. Nevertheless I did convert his java code to C#/Mono For Android and voila, it worked almost immediately (after an hour or so of manual conversion – damn those java’s getters and setters instead of properties).

Attached are the C# sources in case anybody else needs it.

TwoDScrollView.cs (50.08 kb)

SignalR client on Mono for Android

While SignalR is a great library for push notifications it has one “flaw”. There is no included Android client implementation currently, and by Android I mean Mono For Android. Luckily SignalR is an open source project and I decided to see how hard is to make it Mono For Android compatible. It turns out that it is pretty simple.

Here is the recipe (tested on Mono For Android 4.0.x):

  • SignalR depends on Newtonsoft.Json library (free, open source) developed by James Newton-King. Again, there is no Android port included with the original library but there is a port that works fine on Mono For Android. Get it here.
  • Get SignalR client sources. Create new Mono For Android class library and import all (WindowsPhone version of the project) files. Add WINDOWS_PHONE conditional compilation symbol to Project Properties/Build. Then reference the Newtonsoft.Json libary.
  • Mono For Android is currently missing TaskExtensions class required for unwrapping tasks. Get the sources for this class here. I assume it will appear in Mono For Android sooner or later. Add this class to the library and add proper using statements if/where necessary.

That’s it. You are now ready to receive SignalR push notifications.

Here is how you create a PersistentConnection (server part), and here is client code (that runs fine on Mono For Android).

Download the libraries and sources below

 MonoForAndroid.SignalR.Client.zip (1.40 mb)