Sto provando a make as many HTTP requests to a URL as possible, as quickly as possible.Come determinare il collo di bottiglia della richiesta HTTP concomitante in .NET?
Sto usando questo codice per consentirmi di limitare i gradi di Parallelismo massimo, quindi non sovraccarico la memoria generando un sacco di Tasks
contemporaneamente.
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);
}));
}
Sembra funzionare correttamente.
body()
si riduce essenzialmente a:
async Task Body()
{
var r = WebRequest.Create("// the url");
await r.GetResponseAsync();
}
Tuttavia, mi sembra di avere un collo di bottiglia da qualche parte. Se provo e faccio 2500
iterazioni, con valori che variano per dop
ottengo questi risultati:
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
che sembrano suggerire che dop=50
è inferiore il collo di bottiglia. Tuttavia, se superi il valore di dop~=100
, il tempo di esecuzione di ogni richiesta è pari avolte superiore a 2500
) con incrementi quasi lineari con DOP
(c'è un po 'di rumore in questi risultati, ma è ripetibile con piccolo errore).
Questo suggerisce che c'è una "coda" all'interno dell'opera body
, giusto?
Sono già modificando
ServicePointManager.DefaultConnectionLimit = int.MaxValue;
e se faccio
servicePoint = ServicePointManager.FindServicePoint("// the url", null);
e monitorare
servicePoint.CurrentConnections
su ogni esecuzione di body
, la sua sempre uguale a dop
(eccetto la rampa iniziale e la coda fuori).
Ho provato questo da varie reti, quindi è improbabile che sia basato su hardware, e non dovrebbe essere il server remoto come è progettato per carichi pesanti in entrata (non che i numeri di cui sto parlando sono anche pesanti)
Come posso definire meglio quello che sto facendo?
Qui ci sono molte possibilità, ma la mia prima ipotesi sarebbe che stai colpendo il limite di connessione simultanea di Windows.Un'altra possibilità è che l'hardware del server tratti le tue connessioni come un potenziale attacco DOS e le strozzature. –
Media di cosa? Per richiesta o totale? Pubblica il codice di misurazione. – usr
@usr Tempo medio di esecuzione 'corpo' 2500 volte, non chiarire la domanda –