0

I'm trying to understand how parallelization works in Durable Function. I have a durable function with the following code (followed this tutorial: https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-sub-orchestrations?tabs=csharp#example)

        [FunctionName(nameof(OrchestratorFunction))]
        public async Task RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {           
            var items = await context.CallActivityAsync<List<Item>>(nameof(GetItemFunction), null);
            if (items != null && items .Count > 0)
            {
                var processingTasks = new List<Task>();
                foreach (var item in items)
                {
                    Task processTask = context.CallSubOrchestratorAsync(nameof(SubOrchestratorFunction), item);
                    processingTasks.Add(processTask);
                }
                await Task.WhenAll(processingTasks);               
            }
        }

        [FunctionName(nameof(SubOrchestratorFunction))]
        public async Task RunSubOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            var item = context.GetInput<Item>();            
            var name = await context.CallActivityAsync<Item>(nameof(GetNameFunction), item);
            var age = await context.CallActivityAsync(nameof(GetAgeFunction), item);
            var address = await context.CallActivityAsync(nameof(GetAddressFunction), item);            
            var state = await context.CallActivityAsync(nameof(GetStateFunction), item);
            var country = await context.CallActivityAsync(nameof(GetCountryFunction), item);            
        }  

What I wanted to do is to get all items and all items should run in parallel.

Does this code run all the items in parallel? Meaning the time taken by 10 items and 10000 items will be the same? On testing, I see a difference in the time taken by 10 items and 10000 items. Am I missing something?

user989988
  • 3,006
  • 7
  • 44
  • 91

1 Answers1

1

There are many factors that affect the runtime for durable functions that will probably significantly change the runtime for very big workloads compared to smaller ones. One such is time to scale out from 1 to 200 instances.

There is also the fact that activity functions are based on queue triggers which I think wait for a duration of 30 seconds before scaling out again, each has a warmup time as well. (May be special for activities compared to normal queues)

I don't know the exact logic for scaling out but it may not choose to do so if the control queue is not getting bigger. You can through the portal see how many instances and threads you have running. For VERY large tasks it may also be throttled by the queue or tables that are used internally.

It is also dependent on your dependencies in your activities. If you are making API calls or sending emails then those services also need to be able to handle 10000 simultaneous requests.

There is also the fact that you are limited by cores per instance. Let's say 4. Which gives you 800 cores. I think each runs at most 10 threads for activities which means that it may only attempt to process 8000 activities simultaneously (could be somewhere from 800 to 8000 depending on computational work).

These are some reasons that I can think of that would maybe limit larger processes. There is probably more information about how all this works. Some things can also be configured. How does parallelization compare to running everything in sequence?

Docs: https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-perf-and-scale

https://joonasw.net/view/how-azure-durable-functions-scale

https://github.com/Azure/azure-functions-durable-extension/issues/1686

https://github.com/Azure/azure-functions-durable-extension/issues/1686

Take my guessed reasons with a grain of salt. I don't know the exact details and numbers of the inner workings but gives some ideas that can be extended. In any case, expecting them to finish at the exact same time is highly unreasonable. The important point is that the total runtime is quite smaller than no parallelization.

Bjorne
  • 1,424
  • 7
  • 13
  • Thank you! What does it mean when 'Enforce Scale Out Limit' is set to 'No'? – user989988 Jun 17 '21 at 05:49
  • Also, which will take less time - set ‘enforce scale out limit’ to No or set to 200 instances? – user989988 Jun 17 '21 at 06:11
  • Enforce Scale Out Limit is just a toggle if you want to limit the maximum amount of instances. If no it may scale from 0-200 if yes then it may scale from 0-(Maximum scale out limit option). If you really need it to run faster than 10 minutes then I would suggest debugging the number of instances and how that fluctuates aswell as finding bottlenecks in your activities. – Bjorne Jun 17 '21 at 07:45