[英]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 版本,可能存在的問題很少。
HttpClient
實例,例如 這里解釋的原因。work.url
和work.anotherUrl
使用相同的域子集,您應該查看每個端點的連接限制(以及總數)。 取決於HttpClientHandler.MaxConnectionsPerServer或ServicePoint.ConnectionLimit和ServicePointManager.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.