Remove per-message Task.Run from Service Bus inline message deserialization
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 74/100
- Issue type
- Refactor
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- azure, csharp
- Domain
- backend, performance
Research direction
Start in src/DurableTask.ServiceBus/Common/ServiceBusUtils.cs at LoadMessageStreamAsync, then inspect the batch deserialization call sites in ServiceBusOrchestrationService.cs. Add coverage for both target-framework branches and verify inline tasks are already complete while external blob loading remains unchanged. Compare batch behavior at the default prefetch size using the requested performance measures.
Written by the indexing model from the issue text.
Description
What is the issue
ServiceBusUtils.LoadMessageStreamAsync queues synchronous, in-memory work to the thread pool for every message whose body is stored inline:
For netstandard2.0, the work is only new MemoryStream(message.Body). For net48, message.GetBody<Stream>() reads the already-received brokered-message body. Neither branch performs asynchronous I/O, but both use Task.Run.
The orchestration and tracking receivers deserialize whole batches through this method using Task.WhenAll:
The configured prefetch count is 50, so a full batch can enqueue 50 trivial thread-pool work items at once:
Performance impact
Each inline message creates and schedules an unnecessary work item plus its task/delegate state. Under sustained load, batches from multiple dispatchers create bursts of thread-pool queueing that add scheduling latency, consume worker threads, and increase short-lived allocations. Thread-pool ramp-up or contention can amplify first-batch and tail latency even though there is no I/O to overlap.
The overhead scales with message rate and is paid before every inline task-message deserialization. The external-blob path is genuinely asynchronous and is not affected by this concern.
Proposed backward-compatible solution
Keep the existing private Task<Stream> signature and return an already-completed task for inline bodies:
#if NETSTANDARD2_0
return Task.FromResult<Stream>(new MemoryStream(message.Body));
#else
return Task.FromResult(message.GetBody<Stream>());
#endif
This preserves the same stream construction and downstream deserialization behavior while removing the thread-pool hop. Leave the blob-store load path unchanged.
Validation
- Add coverage for both target-framework branches confirming that inline bodies deserialize identically and the returned task is already complete.
- Retain integration coverage for external blob-backed messages.
- Benchmark batch deserialization at the default prefetch size, comparing elapsed time, allocations, thread-pool work-item count, and tail latency.
- Dominant language
- C#
- Stars
- 1.7k
- Forks
- 335
- Avg merge
- 5d 3h
- Merged PRs (30d)
- 8
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Azure/durabletask
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
Azure/durabletask#1398 · 2 comments ·
Maintainers usually reply within 3 days
-
Azure Storage backend: control queue partition left unowned for hours/days after lease expiresMay be free again @nytian claimed this 34 days ago, and no pull request is open. Open
Azure/durabletask#1389 · 1 comment · 1 assignee ·
Maintainers usually reply within 3 days
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
Azure/durabletask#1332 ·
Maintainers usually reply within 3 days
-
Difficulty 3/5 1-2 days Newbie friendliness 58/100
Azure/durabletask#1318 · 1 comment ·
Maintainers usually reply within 3 days
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
Azure/durabletask#1301 · 3 comments ·
Maintainers usually reply within 3 days
All issues in Azure/durabletask
Similar issues
-
test
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
NethermindEth/nethermind#14274 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
area:frontend bug FE P3
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
klasolsson81/jobbliggaren#2023 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
shimat/opencvsharp#2154 ·
Maintainers usually reply within 1 day
-
subsystem: UI
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Open-Systems-Pharmacology/PK-Sim#3812 ·
Maintainers usually reply within 1 day