2015-12-27 18 views
5

Próbuję wykonać make as many HTTP requests to a URL as possible, as quickly as possible.Jak określić równoczesne wąskie gardło żądania HTTP w .NET?

Używam tego kodu, aby umożliwić mi ograniczenie maksymalnych stopni równoległości, więc nie przepełniam pamięci przez jednoczesne odradzanie się wielu partycji o łącznej wartości 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); 
      })); 
    } 

Wygląda na to, że działa dobrze.

body() zasadniczo sprowadza się do:

async Task Body() 
{ 
    var r = WebRequest.Create("// the url"); 
    await r.GetResponseAsync(); 
} 

Jednak wydaje się, że wąskie gardło gdzieś. Gdyby spróbować i zrobić 2500 iteracji, z różnym wartości dla dop uzyskać te wyniki:

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 

które zdają się sugerować, że dop=50 jest mniejsza niż wąskie gardło. Kiedy jednak uzyskasz wartość powyżej dop~=100, zauważysz, że czas każdego żądania wynosi Average (średnia z tego, ile czasu zajmuje Func<T, Task> body, aby uruchomić 2500 razy) rośnie prawie liniowo z DOP (w tych wynikach jest nieco szumu, ale są one powtarzalne z małym błędem).

Sugeruje to, że istnieje "kolejka" wewnątrz pracy body, prawda?

mam już zachodziło

ServicePointManager.DefaultConnectionLimit = int.MaxValue; 

i jeśli mogę zrobić

servicePoint = ServicePointManager.FindServicePoint("// the url", null); 

i monitorować

servicePoint.CurrentConnections 

na każdej realizacji body, jego zawsze równa dop (z wyjątkiem początkowe podniesienie i oderwanie).

Próbowałem tego z różnych sieci, więc jest to mało prawdopodobne, aby był oparty na sprzęcie, i nie powinien być serwerem zdalnym, ponieważ jest przeznaczony do dużych obciążeń wejściowych (nie, że liczby, o których mówię są nawet ciężkie)

Jak mogę lepiej profilować to, co robię?

+0

Istnieje wiele możliwości, ale domyślam się, że trafiasz w limit jednoczesnych połączeń w systemie Windows.Inną możliwością jest to, że sprzęt serwera traktuje połączenia jako potencjalny atak DOS i dławienie ich. –

+0

Śr. Co? Na żądanie lub łącznie? Opublikuj kod pomiarowy. – usr

+0

@usr Średni czas wykonania 'body' 2500 razy, źle wyjaśnij pytanie –

Odpowiedz

1

Łączny czas wykonania wszystkich tych poziomów pracy od 9 do 11 sekund. Ma to sens, ponieważ zwiększając DOP (wykładniczo), w końcu nasycimy zasób backendu, sieć lub coś innego.

Założę się, że gdybyś opublikował niższe wartości benchmarku DOP, zobaczylibyśmy wyższe całkowite czasy.

Po dwukrotnym zwiększeniu liczby równoczesnych żądań podwojenie średniego czasu realizacji.

Sprawdź przepustowość mierzoną w sztukach na sekundę lub całkowity czas. To interesująca metryka. Opóźnienie na element nie jest.

+0

Tak, zrobiłem wiele testów i snipped wyniki dla zwięzłości. <75 dop widzi całkowity wzrost czasu liniowo zgodnie z oczekiwaniami. Prawdopodobnie dla przedmiotów/ów muszę mierzyć przedmioty wypełniające/s. Servicepoint.currentconnections jest zawsze == dop, ponieważ kolejkowanie wydaje się być głębsze niż mój kod. –

+0

Czy możesz opublikować cały kod używany do pomiaru tego? Nie jest jasne, co oznaczają te liczby. Czy możesz także powiedzieć, jakich rezultatów oczekiwałeś? – usr

+0

Oto mój kod, korzystam z usługi AWS SES (do której mogę wysłać 1000/s wniosków - po tym powinienem zobaczyć dławienie) https://gist.github.com/trullock/a112885d374a081aee4d –

Powiązane problemy