Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NET TPL线程性能问题_.net_Multithreading_Performance_Task Parallel Library_Semaphore - Fatal编程技术网

.NET TPL线程性能问题

.NET TPL线程性能问题,.net,multithreading,performance,task-parallel-library,semaphore,.net,Multithreading,Performance,Task Parallel Library,Semaphore,我正在从事网页抓取项目,我正在使用.NETCore2.0。我的客户提供了大约100万个域名,客户要求我检查域名是否处于活动状态,并检查响应是否正常。我的代码如下。当我从文件中读取域时,我没有任何问题,性能非常好 我的问题是,当我使用PLINQ并检查域是否处于活动状态时,它只使用一个线程,而对于25000个域,这大约需要一个小时。当我使用信号量方式时,性能很好,有时,结果中的域计数与输入不匹配。例如,在25000个域中,我得到的结果是24798个,我不知道剩下的202个域在哪里。如何提高性能以及代

我正在从事网页抓取项目,我正在使用.NETCore2.0。我的客户提供了大约100万个域名,客户要求我检查域名是否处于活动状态,并检查响应是否正常。我的代码如下。当我从文件中读取域时,我没有任何问题,性能非常好

我的问题是,当我使用PLINQ并检查域是否处于活动状态时,它只使用一个线程,而对于25000个域,这大约需要一个小时。当我使用信号量方式时,性能很好,有时,结果中的域计数与输入不匹配。例如,在25000个域中,我得到的结果是24798个,我不知道剩下的202个域在哪里。如何提高性能以及代码中缺少的内容?请帮忙。这里我提供PLINQ和信号量版本的代码

信号量版本

        var semaphore = new Semaphore(200, 225);
        var allDomains = new List<BsonDocument>();
        try
        {
            foreach (var domain in domainList)
            {
                var cT1 = Task.Factory.StartNew(() =>
                {
                    try
                    {
                        semaphore.WaitOne();
                        Interlocked.Increment(ref countThreads);
                        var active = IsDomainActive(domain) ? true : false;
                        lock (allDomains) allDomains.Add(
                            new BsonDocument
                            {
                                {"Url", domain},                                    
                                {"Active", active},                                    
                                {"CreatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)},
                                {"UpdatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)}
                            }
                        );
                    }
                    finally
                    {
                        semaphore.Release();
                        Interlocked.Decrement(ref countThreads);
                    }
                }, TaskCreationOptions.LongRunning);
            }
        }
        finally
        {
            if (semaphore != null)
            {
                semaphore.Dispose();
                semaphore = null;
            }
        }
var allDomains = (
            from domain in domainList.AsParallel().WithCancellation(cancellationToken).WithDegreeOfParallelism(7).WithExecutionMode(ParallelExecutionMode.ForceParallelism)
            where IsDomainActive(domain)
            select new BsonDocument
            {
                {"Url", domain},                   
                {"CreatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)},
                {"UpdatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)}
            }).ToList();


 private static bool IsDomainActive(string url)
    {
        var domain = new StringBuilder();
        domain.Append("http://");
        domain.Append(url);
        Console.WriteLine($"IsDomainActive: {url:00} - On Thread " + $"{Thread.CurrentThread.ManagedThreadId:00}. Concurrent: {countThreads}");
        try
        {                               
            var request = (HttpWebRequest) WebRequest.Create(new Uri(domain.ToString()));             
            request.Timeout = 5000;
            request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
            var response = (HttpWebResponse)request.GetResponse();
            return (response == null || response.StatusCode != HttpStatusCode.OK) ? false : true;
        }
        catch (Exception e)
        {
            return false;
        }
    }
我的电脑配置如下,问题出现在两种环境中

  • 内存:64GB
  • 处理器:8核
  • 视窗10
  • 我的Linux服务器配置如下

  • 内存:4GB
  • 硬盘驱动器:80GB SSD
  • 操作系统:Ubuntu 16.04
  • 处理器:4芯
  • @编辑1

    我已经用HttpClient.GetAsync更新了代码,但是性能仍然很慢,甚至1000个域都需要很多时间

    private static async Task<bool> IsDomainActive(string url)
        {
            var domain = new StringBuilder();
            domain.Append("http://");
            domain.Append(url);
            Console.WriteLine("Processing Domain: " + url);
            try
            {
                var sessionId = (new Random()).Next().ToString();
                var netProxy = new WebProxy("<proxyserver>", port);
                login = "<login>";
                password = "<password>";
                netProxy.Credentials = new NetworkCredential(login, password);
                var handler = new HttpClientHandler()
                {
                    Proxy = netProxy,
                    UseProxy = true,
                };
                var httpClient = new HttpClient(handler);
                var request = new HttpRequestMessage() {
                    RequestUri = new Uri(domain.ToString()),
                    Method = HttpMethod.Get
                };
                request.Headers.Add("Timeout","5000");
                request.Headers.Add("UserAgent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2");
                var response = await httpClient.SendAsync(request).ConfigureAwait(false);
                response.EnsureSuccessStatusCode();
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }
    
    私有静态异步任务IsDomainInactive(字符串url)
    {
    var domain=新的StringBuilder();
    domain.Append(“http://”);
    domain.Append(url);
    Console.WriteLine(“处理域:+url”);
    尝试
    {
    var sessionId=(new Random()).Next().ToString();
    var netProxy=newwebproxy(“,端口);
    登录名=”;
    密码=”;
    netProxy.Credentials=新的网络凭据(登录名、密码);
    var handler=new-HttpClientHandler()
    {
    Proxy=netProxy,
    UseProxy=true,
    };
    var httpClient=新的httpClient(处理程序);
    var request=newhttprequestmessage(){
    RequestUri=新Uri(domain.ToString()),
    Method=HttpMethod.Get
    };
    添加(“超时”,“5000”);
    添加(“UserAgent”、“Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/535.2(KHTML,类似Gecko)Chrome/15.0.874.121 Safari/535.2”);
    var response=await-httpClient.sendaync(请求).ConfigureAwait(false);
    response.EnsureSuccessStatusCode();
    返回true;
    }
    捕获(例外e)
    {
    返回false;
    }
    }
    
    @编辑2 将列表更改为并发

    private static List<BsonDocument> ProcessFile(ConcurrentBag<string> domains, IProgress<string> progress,
            CancellationToken cancellationToken)
        {
           
            var allDomains = (from domain in domains.AsParallel().WithCancellation(cancellationToken)
                    .WithDegreeOfParallelism(Environment.ProcessorCount)
                    .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
                where IsDomainActive(domain).Result
                select new BsonDocument
                {
                            {"Url", domain},                           
                            {"Protocol", "http"},
                            {"CreatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)},
                            {"UpdatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)}
                }).ToList();
            return allDomains;
        }
    
    私有静态列表进程文件(ConcurrentBag域、IProgress进程、,
    取消令牌(取消令牌)
    {
    var allDomains=(来自domains.aspallel()中的域,带有取消(cancellationToken)
    .具有并行度(Environment.ProcessorCount)
    .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
    其中IsDomainActive(域).Result
    选择新的B文档
    {
    {“Url”,域},
    {“协议”,“http”},
    {“CreatedOn”,DateTime.SpecifyKind(DateTime.Now,DateTimeKind.Local)},
    {“UpdatedOn”,DateTime.SpecifyKind(DateTime.Now,DateTimeKind.Local)}
    }).ToList();
    返回所有域;
    }
    
    我已经解决了这个问题,并在linux中进行了测试,效果良好。谢谢大家。我使用Parallel.Foreach()代替信号量方法,检查了线程的创建,并用输入验证了结果。明天的演示一切看起来都很好

    为什么平行度设置为7?为什么不使用诸如HttpClient.GetAsync()之类的本机异步调用?我设置DegreeOfParallelism=7的原因。我的电脑配置为8核处理器。测试完成后,我计划更改为Environment.ProcessorCount。因为我的电脑和服务器配置不同。在何处使用HttpClient.GetAsync()?请让我知道。任何帮助都将不胜感激。您使用的是非线程安全集合,不能在并行代码中使用列表。不要重用HtpClient实例。您不必在第一个版本的代码中等待任务,这就是为什么它会更快。谢谢。我已经用我的问题更新了代码。因为在注释中,它不允许我添加代码:-(不知道为什么。