我正在尝试make as many HTTP requests to a URL as possible, as quickly as possible。
我正在使用此代码来限制最大并行度,因此我不会通过一次产生很多Tasks
来溢出内存。
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(dop)
select Task.Run(async delegate {
using (partition)
while (partition.MoveNext())
await body(partition.Current);
}));
}
这似乎工作正常。
body()
本质上可以归结为:async Task Body()
{
var r = WebRequest.Create("// the url");
await r.GetResponseAsync();
}
但是,我似乎在某个地方存在瓶颈。如果我尝试使用不同的
2500
值进行dop
迭代,则会得到以下结果:DOP: 50
Total Time: 00:00:14.4801781
Average (ms): 246.6088
StDev: 84.1327983759009
DOP: 75
Total Time: 00:00:09.8089530
Average (ms): 265.758
StDev: 110.22912244956
DOP: 100
Total Time: 00:00:11.9899793
Average (ms): 344.9168
StDev: 173.281468939295
DOP: 200
Total Time: 00:00:09.1512825
Average (ms): 627.0492
StDev: 572.616238312676
DOP: 500
Total Time: 00:00:09.3556978
Average (ms): 1361.5328
StDev: 1798.70589239157
DOP: 750
Total Time: 00:00:12.6076035
Average (ms): 2009.058
Normal Total: 5022646
StDev: 2348.20874093199
DOP: 1000
Total Time: 00:00:11.4721195
Average (ms): 2453.782
StDev: 2481.56238190299
DOP: 2000
Total: 00:00:11.6039888
Average (ms): 4100.5536
StDev: 2459.36983911063
这似乎表明
dop=50
小于瓶颈。但是,当您超过dop~=100
时,您会注意到每个请求所花费的Average
时间(即Func<T, Task> body
运行2500
时间所花费的平均时间)与DOP
几乎呈线性增加(这些结果中确实会有一些噪音,但可以重复)误差很小)。这表明
body
正在执行的工作中存在一个“队列”,对吗?我已经在设定
ServicePointManager.DefaultConnectionLimit = int.MaxValue;
如果我愿意
servicePoint = ServicePointManager.FindServicePoint("// the url", null);
并监视
servicePoint.CurrentConnections
在每次执行
body
时,其始终等于dop
(除了初始斜升和尾移外)。我已经在各种网络上进行了尝试,因此它不太可能是基于硬件的,它不应该是远程服务器,因为它是为沉重的入站负载而设计的(不是我所说的数字甚至很沉重)
如何更好地描述自己在做什么?
最佳答案
执行所有这些工作级别的总时间在9到11秒之间。这是有道理的,因为当(按指数)增加DOP时,您最终将使后端资源或网络或其他东西饱和。
我敢打赌,如果您发布的DOP基准数字较低,那么我们看到的总时间就会更长。
当您将并发请求数加倍时,平均完成时间将加倍。
查看以每秒项目数或花费的总时间衡量的吞吐量。这是有趣的指标。不是每个项目的延迟。
关于c# - 如何确定.NET中的并发HTTP请求瓶颈?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34485005/