我正在尝试尽可能快地向URL发出尽可能多的HTTP请求.
我正在使用这段代码来限制最大的并行度,所以我不会通过Tasks
一次性产生大量的内容来溢出内存.
public static Task ForEachAsync(this IEnumerable source, int dop, Func 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
即运行2500
时间的平均值)几乎呈线性增加DOP
(这些结果中的噪声确实存在,但它们可以重复,但误差很小).
这表明工作中有一个"队列" body
正在做,对吧?
我已经开始了
ServicePointManager.DefaultConnectionLimit = int.MaxValue;
如果我这样做
servicePoint = ServicePointManager.FindServicePoint("// the url", null);
和监视器
servicePoint.CurrentConnections
在每次执行时body
,它总是等于dop
(除了初始加速和尾部关闭).
我从各种网络尝试过这个,所以它不太可能是基于硬件的,它不应该是远程服务器,因为它设计用于大量入站负载(不是我所说的数字甚至很重)
我怎样才能更好地描述我在做什么?