首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >高效地使用数千个具有超时的任务

高效地使用数千个具有超时的任务
EN

Stack Overflow用户
提问于 2015-08-27 13:53:09
回答 2查看 791关注 0票数 1

我正在实现一个库L,它通过套接字与另一个应用程序A进行通信。

基本工作流程如下:

  1. L连接到A。
  2. 我向A发送50.000条信息,并为发送的每一个I创建一个任务T。
  3. L侦听来自A的传入结果,一旦重用在那里,使用TaskCompletionSource设置任务T的结果
  4. 创建具有设置超时的任务T2 (Task.WhenAny(T,Task.Delay(Xx)
  5. L使用Task.WhenAll(T2)等待所有发送信息的超时或结果。

管理底层数据结构根本不是问题。主要的问题是,在我的计算机上组装“主”Task.WhenAll(T2)大约需要5-6秒,输入大约50.000个条目(创建50.000*2+1任务)。

然而,我不能想出一种更轻量级的方式来完成同样的任务。它应该使用所有可用的内核,并且是非阻塞的,并且支持超时.

是否有一种方法可以使用提高性能的并行或ThreadPool类来完成相同的任务?

编辑:显示基本设置的代码:https://dotnetfiddle.net/gIq2DP

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-27 14:44:26

总共启动n个LongRunningTasks,其中n是机器上的核数。每个任务应该在一个核心上运行。为您想发送的每一个I创建50K新任务将是一种浪费。相反,设计接受I和套接字信息的任务--其中将发送此信息。

创建一个BlockingCollection<Tuple<I, SocketInfo>>。启动一个任务来填充这个阻塞集合。前面创建的其他n个长期运行的任务可以继续获取信息元组和地址来发送信息,然后在一个循环中为您执行该工作,当阻塞收集完成时,该循环将中断。

可以在长期运行的任务本身中设置超时。

整个设置将使您的CPU最大限度地忙于有用的工作,而不是让它无谓地忙于创建50K任务的“作业”。

由于主内存以外发生的操作(如这个网络操作)是用于CPU的very very slow,所以可以随意设置n,不仅等于机器中的核数,甚至是这个值的三倍。在我的代码演示中,我将其设置为仅等于核心的数量。

有了提供的链接上的代码,这是一种方法.

代码语言:javascript
复制
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Net.NetworkInformation;
using System.Threading.Tasks;

namespace TestConsoleApplication
{
    public static class Test
    {
        public static void Main()
        {
            TaskRunningTest();
        }

        private static void TaskRunningTest()
        {
            var s = new Stopwatch();
            const int totalInformationChunks = 50000;
            var baseProcessorTaskArray = new Task[Environment.ProcessorCount];
            var taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None);
            var tcs = new TaskCompletionSource<int>();

            var itemsToProcess = new BlockingCollection<Tuple<Information, Address>>(totalInformationChunks);

            s.Start();
            //Start a new task to populate the "itemsToProcess"
            taskFactory.StartNew(() =>
            {
                // Add Tuples of Information and Address to which this information is to be sent to.
                Console.WriteLine("Done intializing all the jobs...");
                // Finally signal that you are done by saying..
                itemsToProcess.CompleteAdding();
            });

            //Initializing the base tasks
            for (var index = 0; index < baseProcessorTaskArray.Length; index++)
            {
                var thisIndex = index;
                baseProcessorTaskArray[index] = taskFactory.StartNew(() =>
                {
                    while (!itemsToProcess.IsAddingCompleted && itemsToProcess.Count != 0)
                    {
                        Tuple<Information, Address> item;
                        itemsToProcess.TryTake(out item);
                        //Process the item
                        tcs.TrySetResult(thisIndex);
                    }
                });
            }

            // Need to provide new timeout logic now
            // Depending upon what you are trying to achieve with timeout, you can devise out the way

            // Wait for the base tasks to completely empty OR
            // timeout and then stop the stopwatch.
            Task.WaitAll(baseProcessorTaskArray); 
            s.Stop();
            Console.WriteLine(s.ElapsedMilliseconds);
        }

        private class Address
        {
            //This class should have the socket information
        }

        private class Information
        {
            //This class will have the Information to send
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2015-08-27 15:03:00

分析表明,大多数时间(90%?)用于计时器的安装、过期和处理。这在我看来是可信的。

也许您可以创建自己的超级廉价超时机制。按过期时间排序的优先级队列中的队列超时。然后,每100 is运行一个定时器,并使该定时器过期优先级队列中的所有到期。

这样做的成本将是每次超时一个TaskCompletionSource和一些小的进一步处理。

您甚至可以通过从队列中删除超时并删除TaskCompletionSource来取消超时。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32251280

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档