HttpWebRequest замедляется при добавлении интервала
Тестируя различные возможности загрузки источника веб-страницы, я получил следующие результаты (Среднее время в мс до google.com, 9gag.com):
- Обычный HttpWebRequest: 169, 360
- Gzip HttpWebRequest: 143, 260
- WebClient GetStream: 132, 295
- WebClient DownloadString: 143, 389
Поэтому для моего 9gag-клиента я решил взять gttip HttpWebRequest. Проблема в том, что после реализации в моей реальной программе запрос занимает более чем вдвое больше времени.
Проблема также возникает при добавлении Thread.Sleep между двумя запросами.
РЕДАКТИРОВАТЬ:
Просто немного улучшил код, проблема та же: при циклическом выполнении запросы занимают больше времени, когда я добавляю задержку между запросами
for(int i = 0; i < 100; i++)
{
getWebsite("http://9gag.com/");
}
Принимает около 250 мс на запрос.
for(int i = 0; i < 100; i++)
{
getWebsite("http://9gag.com/");
Thread.Sleep(1000);
}
Принимает около 610 мс на запрос.
private string getWebsite(string Url)
{
Stopwatch stopwatch = Stopwatch.StartNew();
HttpWebRequest http = (HttpWebRequest)WebRequest.Create(Url);
http.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
string html = string.Empty;
using (HttpWebResponse webResponse = (HttpWebResponse)http.GetResponse())
using (Stream responseStream = webResponse.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
{
html = reader.ReadToEnd();
}
Debug.WriteLine(stopwatch.ElapsedMilliseconds);
return html;
}
Есть идеи, чтобы решить эту проблему?
2 ответа
Возможно, попробуйте это, хотя это может помочь вашему случаю только одного запроса и на самом деле усугубить ситуацию при выполнении многопоточной версии.
ServicePointManager.UseNagleAlgorithm = false;
Вот цитата из документации MSDN для класса HttpWebRequest
Другим вариантом, который может повлиять на производительность, является использование свойства UseNagleAlgorithm. Если для этого свойства установлено значение true, TCP/IP будет пытаться использовать алгоритм TCP Nagle для HTTP-соединений. Алгоритм Nagle объединяет данные при отправке пакетов TCP. Он накапливает последовательности маленьких сообщений в большие TCP-пакеты, прежде чем данные будут отправлены по сети. Использование алгоритма Nagle может оптимизировать использование сетевых ресурсов, хотя в некоторых ситуациях производительность также может ухудшаться. Как правило, при постоянной пропускной способности большого объема улучшение производительности осуществляется с помощью алгоритма Nagle. Но для приложений с меньшей пропускной способностью может наблюдаться снижение производительности.
Приложению обычно не требуется изменять значение по умолчанию для свойства UseNagleAlgorithm, которое имеет значение true. Однако, если приложение использует соединения с малой задержкой, это может помочь установить для этого свойства значение false.
Я думаю, что у вас могут быть утечки ресурсов, так как вы не избавляетесь от всех своих объектов IDisposable при каждом вызове метода.
Дайте эту версию и попробуйте и посмотрите, дает ли она более последовательное время выполнения.
public string getWebsite( string Url )
{
Stopwatch stopwatch = Stopwatch.StartNew();
HttpWebRequest http = (HttpWebRequest) WebRequest.Create( Url );
http.Headers.Add( HttpRequestHeader.AcceptEncoding, "gzip,deflate" );
string html = string.Empty;
using ( HttpWebResponse webResponse = (HttpWebResponse) http.GetResponse() )
{
using ( Stream responseStream = webResponse.GetResponseStream() )
{
Stream decompressedStream = null;
if ( webResponse.ContentEncoding.ToLower().Contains( "gzip" ) )
decompressedStream = new GZipStream( responseStream, CompressionMode.Decompress );
else if ( webResponse.ContentEncoding.ToLower().Contains( "deflate" ) )
decompressedStream = new DeflateStream( responseStream, CompressionMode.Decompress );
if ( decompressedStream != null )
{
using ( StreamReader reader = new StreamReader( decompressedStream, Encoding.Default ) )
{
html = reader.ReadToEnd();
}
decompressedStream.Dispose();
}
}
}
Debug.WriteLine( stopwatch.ElapsedMilliseconds );
return html;
}