Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Investigate spawning too many threads #125

Closed
Shazwazza opened this issue Jun 26, 2019 · 1 comment
Closed

Investigate spawning too many threads #125

Shazwazza opened this issue Jun 26, 2019 · 1 comment
Labels

Comments

@Shazwazza
Copy link
Owner

Based on this convo and below: umbraco/Umbraco.Cloud.Issues#72 (comment)

Need to look into this line:

_asyncTask?.ContinueWith(task => onComplete?.Invoke(new IndexOperationEventArgs(this, task.Result)));

@Shazwazza
Copy link
Owner Author

Shazwazza commented Aug 6, 2019

I have investigated this and based on this comment umbraco/Umbraco.Cloud.Issues#72 (comment) here is what is happening:

When one or many things are indexed using PerformIndexItems(IEnumerable<ValueSet> op, Action<IndexOperationEventArgs> onComplete) it will queue these items in a global queue and it will use Task.Run to start consuming this queue of items to be indexed. If a call is made to PerformIndexItems while the queue is still processing, a new thread is not created. Only one consuming thread will ever be created at a given time to process the queue.

Whenever a call to PerformIndexItems is done, a callback is passed to this method which is executed after this batch of items is done processing. This callback is executed using the currently executing Task's continuation (i.e. ContinueWith). It is true that ContinueWith will use another threadpool thread, however this is no different than using normal async/await which is shortand for doing such things.

Under the covers, the await functionality installs a callback on the task by using a continuation

The callback executed with ContinueWith is ultra fast and all it's doing is raising an event so this is super short lived. When it's done it is returned to the threadpool.

It could potentially be possible to execute PerformIndexItems in a loop with single items say thousands of times which is not really what intended to be done since you can pass in multiple items in one call. However, in that case it could potentially us up a lot of threadpool threads but the execution on these threads in the ContinueWith is extremely small so it's not blocking anything.

Based on the original question above - yes there are 2x ContinueWith calls and this is because the first one is when the queue is empty and there is no worker Task active, so when it is created a ContinueWith is used to ensure the callback is executed. The 2nd one is when the queue is actively being consumed and the ContinueWith is added to the already existing Task so that all callbacks passed to PerformIndexItems are called regardless of if it's starting a new Task to consume the queue or not.

With all of that said, I've found some minor changes that i want to make with how the ContinueWith is being used to ensure they are being passed the cancellation token and that they have the default task scheduler options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant