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;
  }
Другие вопросы по тегам