hquinn
hquinn

Reputation: 100

Best performance using async and await

I have a 1 core machine and I would like to improve my code performance using async and await. The code has two major parts. the first an IO operation. (reading from azure service bus queue for multiple sessionId), the second, processing the data - CPU heavy. I have wrapped the DequeueAsync method in an async method which returns a Task:

private async Task<SomeReturnValue> AcceptFromQueueAsync(){
  try{ 
       SomeReturnValue result = await DequeueAsync.configureAwait(false);
       return SomeReturnValue;  
  }
  catch{
   //logging and stuff
  }

The CPU heavy method is sync: DoSyncWork() Since the second part is CPU heavy I don't want to use parallelism (actually can't... ) The CPU part can only start when the IO part finishes. Given the above is the following implementation the way to go with 1 cpu machine?

private void AcceptAndProcessWrapper(){
    //Count is some cosnt defined outside the method
    _acceptTasks = new List<Task<SomeReturnValue>>();
     for (var i = 0; i < Count; i++)
     {
                    _acceptTasks.Add(AcceptFromQueueAsync());
      }
      //The use of list is for convince in processing  
      Task.WaitAll(_acceptTasks.ToArray());
      //The CPU part 
       Task.Run(DoSyncWork).Wait();
 }

I know that I could have not use the Task.Run() for the sync part but I want to allow feature implementation on multiple cores (By starting several Tasks using Task.Run() and holding them in an array) Will the above implementation. (The multiple calls to async method that returns a task) improve the performance? Or should I start a new Task for each async call e.g Task.Run(AcceptFromQueueAsync)?

Upvotes: 1

Views: 1654

Answers (4)

Agat
Agat

Reputation: 4779

Speaking of performance with Task(s) (if you use it in future with DoSyncWork) you should keep also in mind that Task.Run uses ThreadPool by default, but the threads from Thread pool are rather expected to do some fast and small work. If the tasks are really some "heavy" ones, you should consider running them in newly created threads, which might be also forced with the following:

new Task(() => { }, TaskCreationOptions.LongRunning);

EDIT:

After some talk in commeting below, I would want to clear the stuff up a bit more.

Currently, Task.Run(DoSyncWork).Wait(); really does not have any sense (even more, it might take additional time to run the task on another thread (even from ThreadPool ones), but if you want to use several cores in future, you obviously should move that task to another thread to run (and if it's really CPU-heavy, then consider running the task as "LongRunning") (if it's of course needed for your app (not sure what's the type of app you have)). In that case, there is still no need to call .Wait() there instantly.

Upvotes: 1

Yaur
Yaur

Reputation: 7452

I use a pattern similar to this to try to keep the IO and CPU going as much as possible

public async void DoWork()
{
    Task cpuBoundTask = null;
    Task ioBoundTask = null;

    while(true)
    {
         ioBoundTask = DoIOBoundStuff();
         var ioResult = await ioBoundTask;

         if(cpuBoundTask != null)
         {
             await cpuBoundTask;
         }
         cpuBoundTask = DoCpuBoundStuff(ioResult);
    }
 }

Upvotes: 0

Servy
Servy

Reputation: 203822

The code that you have will indeed do the asynchronous dequeuing in parallel. It will start all of the asynchronous tasks at once and then wait until they are all done to continue.

Adding an extra call to Task.Run won't help. Starting an asynchronous task in another thread is just adding extra overhead for no added value. Task.Run should be used to run CPU bound work in another thread, not asynchronous work in another thread.

Upvotes: 3

Ashigore
Ashigore

Reputation: 4678

Running the first part asynchronously might make sense, depends, it has Async in the name which suggests it doesn't block anyway in which case there is no needed, but there is definitely no need to run DoSyncWork asynchronously since its just 1 process and you are waiting for it to finish.

Upvotes: 0

Related Questions