Search code examples
azure-durable-functions

Using Sub-Orchestrators for Fan-In Performance Increase


I'm running a Durable Function (.NET 7 Isolated Worker) that fans out to 1000s of instances of a particular Activity Function and each instance stores it's contents into the same file in Blob Storage. I read that fanning in only happens on one Orchestrator instance, so using sub-orchestrators could help with the performance of the fan-in.

The Sub-Orchestrators are called from the parent Orchestrator as so:

foreach (var item in userList)
{
    Task subOrchestratorTask = context.CallSubOrchestratorAsync(Constants.SUB_ORCHESTRATOR, new SubOrchestratorInputModel
    {
        item
    });
    subOrchestratorActivities.Add(subOrchestratorTask);
}
await Task.WhenAll(subOrchestratorActivities);

Each of the two Sub-Orchestrators looks like the following:

[Function(Constants.SUB_ORCHESTRATOR)]
public async Task SubOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context, SubOrchestratorInputModel request)
{
    var activities = new HashSet<Task>();
    foreach (var userInfo in request.userIds)
    {
        activities.Add(context.CallActivityAsync(Constants.ACTIVITY_FUNCTION, new ActivityFunctionInput
        {
           userInfo
        }));
    }
    await Task.WhenAll(activities);
}

Is this the proper way to utilize the fan-in with multiple sub-orchestrators? I'm running a fan out of the activity function in each sub-orchestrator but as I'm reviewing the time stamps for each sub-orchestrator, it looks like the first is being updated while the second isn't. I'm wondering if the function is running the first sub-orchestrator, waiting for that to finish, and then running the second sub-orchestrator, versus running in parallel. Here's an image from Storage Explorer of the parent orchestrator (third row) and the sub orchestrators (1st and 2nd rows): enter image description here


Solution

  • The above way is the appropriate way to utilize sub-orchestrators to assist in the fan out/fan in of a Durable Function, just as Microsoft's documentation says. I wasn't sure if it suited my needs as I'm fanning out an activity function inside of fanned out sub-orchestrators. This drastically decreased the time to run my Durable Function.

    The number of sub-orchestrators to use is based on your use case such that you're getting the most out of whatever plan you're running.