question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

BlobWriteStream.Dispose() causes thread starvation under load

See original GitHub issue

Which service(blob, file, queue, table) does this issue concern?

Blob

Which version of the SDK was used?

9.3.0

Which platform are you using? (ex: .NET Core 2.1)

.NET Core 2.1

What problem was encountered?

I’ve been troubleshooting a scalability issue with our ASP.NET Core Web API, which makes heavy use of blob storage for underlying storage.

We observed:

  • Massive sudden increase in response times above a certain number of concurrent clients
  • No corresponding increase in CPU usage
  • No corresponding increase in response time from blob storage

Long story short, through profiling I have finally pinpointed the issue to be here:

https://github.com/Azure/azure-storage-net/blob/38425e715e1bcdb4cab344bcb9b448c08bf8af5c/Lib/WindowsRuntime/Blob/BlobWriteStream.cs#L200-L220

The problem is the CommitAsync().Wait(). Since the dispose pattern in .NET is not async, this stream implementation of course has to block on the commit operation, and the commit is necessary to ensure that the written blocks are committed to blob storage. This blocks the thread for the duration of that commit operation, which under load leads to thread starvation.

Have you found a mitigation/solution?

One solution would be for our service to do await stream.CommitAsync(); before disposing the stream, but unfortunately BlobWriteStream is marked as internal so this type is not visible to our code. The only solution I can think of is to make BlobWriteStream public, allowing client code to asynchronously commit the stream before disposing it.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:1
  • Comments:16 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
DaRosenbergcommented, Aug 20, 2018

@asorrin-msft You are right - that should work without any code change actually, because BlobWriteStream inherits from CloudBlobStream. So from client code we should be able to do something like:

using (var stream = await blob.OpenWriteAsync())
{
  // Do some writing to the stream here...

  if (stream is CloudBlobStream blobStream)
    await blobStream.CommitAsync();
}

The issue of discoverability is something I’ve also been thinking about. An XML doc comment on ´OpenWriteAsync()` will not go very far I’m afraid.

Might one consider taking this so far as to actually throw from Dispose() if the stream has not been committed, thus always forcing the pattern of committing (asynchronously) before disposing? At least that way, it will be a fail-fast and obvious thing very early in the dev lifecycle, instead of a very elusive and hard-to-diagnose scalability problem 18 months down the road when the application is already in production…

1reaction
DaRosenbergcommented, Aug 16, 2019

@justinSelf Duh, of course, stupid of me. The CommitAsync() happening as part of Dispose() was the whole reason why I opened this issue in the first place. 🤣

Read more comments on GitHub >

github_iconTop Results From Across the Web

Troubleshoot threadpool starvation under heavy load
Probably caused by blocking IO requests on the threadpool threads which handle incoming HTTP requests. You should look at async and Tasks.
Read more >
Debug ThreadPool Starvation
ThreadPool starvation occurs when the pool has no available threads to process new work items and it often causes applications to respond ...
Read more >
App service thread starvation : r/AZURE
I'd postulate that it might be a dispose issue. Have you checked that all your disposable resources (in code, I mean) are being...
Read more >
Untitled
Blob.IListBlobItem Inheritance … varakļānietis BlobWriteStream.Dispose() causes thread starvation under load #754 - GitHub CloudBlob Class (Microsoft.Azure.
Read more >
Troubleshooting Thread Starvation in ASP.NET Core on ...
Thread starvation occurs when a thread is unable to gain access to shared resources, causing the application to hang or slow down. This...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found