2015-12-27 13 views
5

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?

+0

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. –

+0

Media di cosa? Per richiesta o totale? Pubblica il codice di misurazione. – usr

+0

@usr Tempo medio di esecuzione 'corpo' 2500 volte, non chiarire la domanda –

risposta

1

Il tempo totale per eseguire tutti i livelli di lavoro compresi tra 9 e 11 secondi. Questo ha senso perché aumentando il DOP (esponenzialmente) alla fine si saturerà la risorsa back-end o la rete o qualcos'altro.

Scommetto che se avessi pubblicato più bassi numeri di benchmark DOP avremmo visto tempi totali più alti.

Quando si raddoppia il numero di richieste simultanee a questo punto, il tempo medio di completamento raddoppia.

Verificare la velocità misurata in unità al secondo o il tempo totale impiegato. Questa è la metrica interessante. La latenza per elemento non lo è.

+0

Sì, ho fatto un sacco di test e ho tagliato i risultati per brevità. <75 dop vede il tempo totale aumentare in modo lineare come ci si aspetta. Presumibilmente per gli articoli/i ho bisogno di misurare gli elementi completando/s. Servicepoint.currentconnections è sempre == dop, poiché la messa in coda sembra più profonda del mio codice. –

+0

Puoi pubblicare tutto il codice usato per misurare questo? Non è chiaro cosa rappresentino quei numeri. Inoltre, puoi dire quali risultati ti aspettavi? – usr

+0

Ecco il mio codice, utilizzando il servizio AWS SES (che mi è stato permesso di inviare richieste 1000/s a ​​- dopo che avrei dovuto vedere la limitazione) https://gist.github.com/trullock/a112885d374a081aee4d –