簡體   English   中英

c# 中的並行任務性能

[英]Parallel tasks performance in c#

我需要讓任務運行得更快,我嘗試使用信號量、並行庫和線程(嘗試為每項工作打開一個,我知道這是最愚蠢的做法),但它們都沒有顯示出我需要的性能。 我不熟悉使用線程的東西,我需要一些幫助來找到正確的方法並了解任務和線程是如何工作的。

這是 function:

 public class Test
    {
        public void openThreads()
        {
            int maxConcurrency = 500;
            var someWork = get_data_from_database();
            using (SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency))
            {
                List<Task> tasks = new List<Task>();
                foreach (var work in someWork)
                {
                    concurrencySemaphore.Wait();

                    var t = Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            ScrapThings(work);
                        }
                        finally
                        {
                            concurrencySemaphore.Release();
                        }
                    });

                    tasks.Add(t);
                }

                Task.WaitAll(tasks.ToArray());
            }
        }

        public async Task ScrapThings(Object work)
        {
            HttpClient client = new HttpClient();
            Encoding utf8 = Encoding.UTF8;
            var response = client.GetAsync(work.url).Result;
            var buffer = response.Content.ReadAsByteArrayAsync().Result;
            string content = utf8.GetString(buffer);
            /*
             Do some parse operations, load html document, get xpath, split things, etc 
             */

            while(true) // this loop runs from 1~15 times
            {
                response = client.GetAsync(work.anotherUrl).Result;
                buffer = response.Content.ReadAsByteArrayAsync().Result;
                content = utf8.GetString(buffer);
                if (content == "OK")
                    break;

                await Task.Delay(10000); //I need some throttle here before it tries again
            }
            /*
                Do some parse operations, load html document, get xpath, split things, etc 
                */
            update_things_in_database();
        }
    }

我想讓這個任務並行運行 500 次,所有操作需要 18 小時才能完成,我需要減少這個,我使用的是 32 核/64 線程的至強。 我嘗試打開 500 個線程(與信號量和並行庫相比性能更好),但感覺不是正確的做法。

我想說性能問題不在於您如何運行線程,而在於各個線程的執行方式。 根據您使用的 .NET/libraries 版本,可能存在的問題很少。

  1. 您應該重用HttpClient實例,例如 這里解釋的原因。
  2. 如果work.urlwork.anotherUrl使用相同的域子集,您應該查看每個端點的連接限制(以及總數)。 取決於HttpClientHandler.MaxConnectionsPerServerServicePoint.ConnectionLimitServicePointManager.DefaultConnectionLimit的版本。 前者用於 .NET 核心,后者用於.NET 完整框架

解決第一個問題的推薦方法是使用IHttpClientFactory

還有更多 信息

UPD

您在評論中提到您正在使用 .NET 4.7.2,因此我建議您首先在您的應用程序中添加下一行(在開頭的某個位置):

ServicePointManager.DefaultConnectionLimit = 500;
// if you can get collection of most scrapped ones:
var domains = new [] { "http://slowwly.robertomurray.co.uk" };
foreach(var d in domains)
{
    var delayServicePoint = ServicePointManager.FindServicePoint(new Uri(d));
    delayServicePoint.ConnectionLimit = 10; // or bigger
}

這聽起來像是TPL Dataflow庫的工作。 對於 I/O 綁定操作(Web 請求、數據庫更新)和 CPU 綁定操作(數據解析),您可能需要不同的並發級別。 TPL 數據流允許構建一個管道,其中每個塊負責一個操作,數據從一個塊流向下一個塊。 它甚至允許循環圖,例如,您可以將失敗的數據元素扔回塊中,以便可以再次處理它。

有關使用此庫的一些示例,請查看此處此處此處

TPL 數據流庫嵌入在 .NET 核心中,並作為.NET框架的 package 提供。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM