Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Azure Function Apps: Performance Considerations

While working with Azure Function Apps we often come across performance issues where we see the rate of message processing or the rate at which API calls are being served is not even near to the expected one.

Before we start digging into these issues I would like to mention that no service/product is perfect. As and when product grows it needs more inputs for improvement. It is possible that even after following the best practices the applications may face issues but then Microsoft is always open for feedback and that’s how we grow and keep improving.

This blog assumes the basic knowledge about the Azure Function App.

Let’s discuss the commonly faced Performance Issues one by one.

When we talk about performance it’s commonly about, but not limited to,

  1. High CPU Consumption
  2. High Memory Consumption
  3. Port/ Outbound Socket Consumption
  4. No. of threads being spawned up.
  5. No of pending requests in the HTTP Pipeline.

While creating a Function App one should keep in mind the fact that moving from Consumption Plan to App Service Plan and vice-versa is not possible once the function is created. However, if you delete the Function app and recreate it on the other type of hosting plan then that is possible for obvious reasons.

Consumption plan takes care of scaling out whenever there is a need. To describe in simple terms scaling happens when the current processing /output Up to 1.5 GB Ram and 1 core CPU is what we get in one instance where the Function app is running, which is not too great I would say. The other limits are:

clip_image001

We should design and develop our function app in a way avoiding performing an intensive tasks taking high CPU, High Memory, spawning large no of threads, opening large no of outbound socket connections etc.

Once the application usage gets past to these limits the processing rate of messages will reduce and then the scale controller adds a new instance of the machine and the load gets distributed to keep up the processing rate.

However, it takes at least 10 seconds to add a new instance and start the load balancing of the events.

Especially with HTTP triggers, it takes a bit longer to add more instances. So if we are running load tests we may see a little bit higher time taken by the requests to complete as they all start to go on a single instance and we can observe the HTTP pipeline growing up initially. However when the new instances are added then processing speeds up and within 20-30 Min of time, the high load(10K requests) will be settled.

This is the case with Consumption plan.

In case we use the app service plan then definitely we are choosing the VM specs we want our application to run on. So with features like auto-scaling, we can have the control on when to trigger scaling and also what size of VM to choose.

This was about the VM and how to manage or effectively utilize the VM resources.

While building the application one should also consider the connections to other services internal or external to Azure which the Function app is going to connect. The limit for no of outbound socket connections alive at any given point in time is 300 on Consumption plan. It seems to be pretty low. However, scale-out happens (indirectly) when this limit is reached.

Now let's see how this works.

Suppose I have a Function app (Consumption Plan) running on one instance and in the Function app itself I am making 400 connections to any other service. Which means I am getting one request to the Function app and I am making 400 connections in my code. In this case, the auto scale-out which happens on consumption plan will not help me as all those outgoing connections are coming from same worker process and same instance of the worker process. Now imagine even if I get multiple instances (I don’t know how, but let’s assume) then each instance will have its own worker process and each worker process will make 400 calls to the external service and every worker process on every instance will start failing.

The consumption plan scaling will work in a scenario where there are 400 requests to the Function app itself and every function call making one connection to external service. So if initially we have one instance it will get 400 calls then as it will not be able to process more than 300 calls (it will make 300 connections to the external service and will consume all 300 ports) the consumption plan scaling will happen and will add a new instance to serve rest of the calls.

Now along with these considerations, we can implement parallel processing of messages by using respective trigger properties in HOST.JSON file of the Function app. These are:

{
 
  "eventHub": {
    "maxBatchSize": 64,
    "prefetchCount": 256,
    "batchCheckpointFrequency": 1
  },
 
  "http": {
    "routePrefix""api",
    "maxOutstandingRequests": 20,
    "maxConcurrentRequests": 10,
    "dynamicThrottlesEnabled"false
  },
 
  "queues": {
    "maxPollingInterval": 2000,
    "visibilityTimeout""00:00:30",
    "batchSize": 16,
    "maxDequeueCount": 5,
    "newBatchThreshold": 8
  },
  "serviceBus": {
    "maxConcurrentCalls": 16,
    "prefetchCount": 100,
    "autoRenewTimeout""00:05:00"
  }
}

Also while connecting to the external connection it’s always advisable to use connection pooling. However, that also depends on what scenario you are working on.

So the considerations discussed above, the concurrent processing properties and connection pooling combined together can significantly improve the function app performance.

Before ending the blog couple of important points I want to share here which are worth keeping in mind when we are comparing the performance of Function app on Consumption plan vs on App Service plan Vs the same code in a Web App on a VM

  1. Compute power of all the three kinds of VM’s are different.
  2. If we are running the same code on the Function app, app service plan and in an application on VM with the similar configuration like RAM and CPU, there will be a difference in computing power observed as the underlying VM’s can be of different series. Web apps use A Series VM which are for moderate loads. When we are choosing the actual VM, we can take it of any series we want and usually we end up in choosing D series VM having high computing power. Here is an article to go through all the series of VM’s available on Azure.

I hope this will give you all a little more insight on the performance issues on Function Apps.

Share the post

Azure Function Apps: Performance Considerations

×

Subscribe to Msdn Blogs | Get The Latest Information, Insights, Announcements, And News From Microsoft Experts And Developers In The Msdn Blogs.

Get updates delivered right to your inbox!

Thank you for your subscription

×