简体   繁体   English

使用async和await的最佳性能

[英]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. 我有一个核心机器,我想使用async和await来提高我的代码性能。 The code has two major parts. 代码有两个主要部分。 the first an IO operation. 第一个IO操作。 (reading from azure service bus queue for multiple sessionId), the second, processing the data - CPU heavy. (从azure服务总线队列读取多个sessionId),第二个,处理数据--CPU重。 I have wrapped the DequeueAsync method in an async method which returns a Task: 我已经在异步方法中包装了DequeueAsync方法,该方法返回一个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. CPU重载方法是同步:DoSyncWork()由于第二部分CPU很重,我不想使用并行性(实际上不能......)CPU部分只能在IO部分完成时启动。 Given the above is the following implementation the way to go with 1 cpu machine? 鉴于以上是以下实现1 cpu机器的方式?

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. 我知道我可能没有使用Task.Run()作为同步部分,但我想允许在多个核心上实现功能(通过使用Task.Run()启动几个任务并将它们保存在一个数组中)请问上面的实现。 (The multiple calls to async method that returns a task) improve the performance? (多次调用返回任务的异步方法)可以提高性能? Or should I start a new Task for each async call eg Task.Run(AcceptFromQueueAsync)? 或者我应该为每个异步调用启动一个新任务,例如Task.Run(AcceptFromQueueAsync)?

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. 添加对Task.Run的额外调用Task.Run 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. Task.Run应该用于在另一个线程中运行CPU绑定工作 ,而不是在另一个线程中的异步工作。

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. 说到使用Task的性能(如果将来使用它与DoSyncWork一起DoSyncWork ),你应该记住Task.Run默认使用ThreadPool,但是线程池中的线程预计会做一些快速和小的工作。 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(); 目前, 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. 真的没有任何意义(甚至更多,可能需要额外的时间在另一个线程上运行任务(即使是从ThreadPool的线程),但如果你想在将来使用多个核心,你显然应该将该任务移动到另一个线程到运行(如果它真的是CPU重,那么考虑将任务作为“ LongRunning ”运行)(如果它当然需要你的应用程序(不确定你的应用程序类型是什么))。在这种情况下,仍然没有需要立即调用.Wait()

异步运行第一个部分可能有意义,取决于它在名称中有Async,表明它不会阻塞,在这种情况下不需要,但是由于它只有1个进程而你绝对不需要异步运行DoSyncWork正在等待它完成。

I use a pattern similar to this to try to keep the IO and CPU going as much as possible 我使用类似于此的模式来尽可能地保持IO和CPU的运行

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);
    }
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM