Azure Resource Manager Batch API
The latest Azure Mobile App update has statuses on the resources list:
You probably want to ask why we didn't have them before. Great question! Currently Azure Resource Manager (public API we are using to get your Azure resources) requires to make separate calls to get single resource status. It means: if you have 100-200 resources, you would have to make 100-200 extra calls. There are some people who has almost 2000 in one subscription! Taking performance and data usage into consideration, this is not ideal.
Both iOS and Android platforms allows to address this problem to some extent by querying for status only resources that are currently visible. However this is still extra 5-10 calls. It is even worse when you start scrolling, and very bad if you scroll on your list containing 2000 resources.
Batch API
Sometime ago ARM added Batch API - you can send POST request with up to 20 URIs in the body. Response will contain up to 20 packaged responses that you have to extract. Using batch API, you can decrease number of requests by up to 20x. This matters especially when user has a lot of resources and keep scrolling on the list.
When implementing batch requests, you need to figure out the optimal interval for sending requests. We started with 200ms, but then we changed it to 50ms. Additionally, every time new request is coming we delay sending batch request by additional 50ms. This may cause indefinite delay. In order to solve this: we always submit request if queue has 20 or more pending requests. 20*50ms = 1000ms = 1s = long time! We tweaked it again, and changed interval to 20ms. With current implementation, we wait anytime between 20ms and 400ms to send batch request.
Implementing Batch API
You probably gonna say: "it all sounds great, but how do I implement it"? For you convenience I created small console application that demonstrate ARM Batch API in action, and I put it on github.
Xamarin.iOS and Xamarin.Android does not have System.Threading.Timer
. We created our own implementation OneShotTimer
(thanks William Moy!).
Entire magic happens in ArmService. It has one public method GetResource
that instead of directly sending GET request is adding request to ConcurrentQueue. OneShotTimer
and BatchRequestDipatcher
methods are responsible for sending the actual HTTP request.
In order to run console app, you need to provide ARM token, and (optionally) resource ids you want to request. In demo app I provided fake resource ids, which will be fine to issue requests, but you will not get resource back.
To get ARM token, go to Azure Portal, open F12 tools and inspect some ARM request. From request headers, copy Authorization header (string starting with Bearer rAnDoMcHaRacTErS...):
You can also get resources ids from F12 tab. The best way is to go to All Resources blade, and find some batch request:
Once you paste resource ids and ArmToken in Program.cs you can run the app, and you should see the following output:
Requests are send in random time, anytime from 0 to 5s after program runs. This is done using Task.Delay:
When you change randomness from 5s to 0.5s you can observe that there will be less batch requests (AKA more requests sent in single batch):
Summary
Using Batch API for getting resource statuses visibly improves performance in the mobile app. It is noticeable especially when using network data.
Azure Resource Manager has plans to add ARM API that will allow to do 1 request to get multiple resources with statuses. This should improve performance even more in the future.
If you are facing similar problem with your app, consider implementing Batch API on your server!