2010-01-12 1 views
9

У меня есть вопрос относительно производительности клиента .Net HttpWebRequest (или WebClient, дает аналогичные результаты)..NET HttpWebRequest Скорость против браузера

Если я использую HttpWebRequest, чтобы запросить html-страницу (в данном случае news.bbc.co.uk) и проанализировать скорость (используя HttpAnalyzer), при которой отклик читается приложением, это значительно медленнее, чем браузер (Firefox, Chrome, IE) с запросом одного и того же ресурса (все кэши очищены и т. Д.). Приложение .Net занимает примерно 1,7 секунды против 0,2 - 0,3 секунды для браузера.

Является ли это чисто снижением скорости и эффективности кода/приложения или есть ли какие-либо другие факторы для рассмотрения?

код следующим образом:

HttpWebRequest request = null; 

Uri uriTest = new Uri("http://news.bbc.co.uk"); 

request = (HttpWebRequest)WebRequest.Create(uriTest); 

request.Method = "GET"; 
request.KeepAlive = true; 
request.Headers["Accept-Encoding"] = "gzip, deflate"; 

HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

response.Close(); 
+1

Используйте IP-адрес вместо URL-адреса, давайте выясним, является ли DNS-сервер источником задержки. –

+1

Извините, я должен был упомянуть, уже попробовал это (замените «http://news.bbc.co.uk» на «http://212.58.226.77» выше), никакой разницы. – Chris

ответ

1

Вы смотрели сети, используя браузер? Возможно, браузер использует кешированные ресурсы?

+0

Я подтвердил, что браузер не использует кешированные ресурсы. – Chris

+1

Я видел эту часть вашего вопроса.Я имел в виду обратное - вы подтвердили, что на самом деле происходит через провод? Сравните _that_ между двумя сценариями. –

+1

Кроме того, вы только рассчитываете до ответа. Вы должны получить 'response.GetResponseStream()' и прочитать все это. –

1

Я посередине Fiddler посередине, запустите запрос браузера и запрос .NET один за другим и убедитесь, что вы действительно получаете то, что думаете. Возможно, существует перенаправление или что-то еще неловкое (возможно, браузер предварительно добавляет '/', в то время как .NET ждет redir и т. Д.), Что не сразу видно. Я построил огромные приложения на HTTP-клиенте .NET, ничего похожего на то, что вы описываете, - что-то еще должно продолжаться.

Что произойдет, если вы нажмете '/' в конце URL-адреса?

+0

Добавление '/' не имеет значения. Будет использовать Fiddler для подтверждения таймингов. – Chris

+1

+1, Fiddler покажет вам, что передаёт, если это gzip'd и т. Д. – orip

+0

Fiddler создан с .NET –

0

Возможно, bbc.co.uk проверяет переданный ему User-Agent header и обрабатывает ответ на основе этого. Поэтому, если он видит автоматизированных клиентов, тогда он реагирует медленно, где, как если бы он полагал, что есть настоящий человек в конце строки, он ускоряется. Если вы действительно хотите попробовать, просто скажите HttpWebRequest, чтобы передать другой заголовок.

+0

Добавлен тот же User-Agent, что и Firefox, с теми же результатами. – Chris

1

Что такое разбивка на 1,7? Я подозреваю, что вы измеряете весь процесс?

Используя этот кусок кода я получаю около 200 мс в среднем:

var request = (HttpWebRequest)WebRequest.Create("http://www.bbc.co.uk/news/"); 

var stopwatch = new Stopwatch(); 
stopwatch.Start(); 

using (var response = (HttpWebResponse)request.GetResponse()) 
{ 
    stopwatch.Stop(); 
    Console.WriteLine("Elapsed: {0}ms", stopwatch.ElapsedMilliseconds); 

    var responseStream = response.GetResponseStream(); 
    if (responseStream != null) 
     using (var sr = new StreamReader(responseStream)) 
      Console.WriteLine("Title: {0}", Regex.Match(sr.ReadToEnd(), @"title>(.*)</title").Groups[1].Value); 
} 

Редактировать изменил код просто измерить фактический запрос HTTP в и попробовал еще раз, используя Fiddler, а также:

Программа, вышеперечисленная: Истек: 78 мс

Скрипач: Истекшее: 00: 00: 00.0620000

2

Если вы делаете два запроса, то второй происходит быстрее?

Я также заметил различия в скорости между браузерами и WebClient или WebRequest. Даже необработанная скорость ответа может быть резко различной - но не все время!

Есть несколько вещей, это может быть вызвано следующими причинами:

  • Это может быть все, что .Net самонастройки происходит. ,Чистые сборки не загружаются и JIT до тех пор, пока они не используются, поэтому вы можете увидеть значительное снижение скорости при первоначальном вызове части кода, даже если само приложение работает уже давно. Хорошо, поэтому сама инфраструктура .Net - это nGen'd, но до сих пор существует мост между вашим кодом и инфраструктурой .Net, чтобы строить «на лету».

  • Просто проверьте, что вы работаете без прикрепленного отладчика, и что у вас определенно нет сервера символов - сервер символов и VS прерывает программы при загрузке этих символов, замедляя их загрузку. Извините, если это оскорбление;)

  • Браузеры кодируются, чтобы эффективно использовать только несколько базовых сокетов; и они будут открыты и загрунтованы, как только появится браузер. «Наш» код, который использует .Net WebClient/WebRequest, совершенно неэффективен в сравнении, поскольку все инициализируется заново каждый раз.

  • Существует множество ресурсов платформы, связанных с сетью, и в то время как .Net упрощает кодирование сетей, оно по-прежнему связано с теми же проблемами ресурса платформы. Эрго, чем ближе вы к платформе, тем быстрее будет какой-то код. IE и Firefox и др. Являются родными и поэтому могут быть выброшены из системных ресурсов изначально; .Net не является, и поэтому для определения вещей требуется некоторая сортировка (= медленная). Очевидно, что когда порт открыт и используется, однако, .Net все еще не сутулится; но он почти никогда не будет таким быстрым, как хорошо написанный немаршаллированный собственный код.

1

Запустите приложение с помощью Ctrl + F5 вместо F5 (режим отладки). Вы увидите разницу:

class Program 
{ 
    static void Main() 
    { 
     using (var client = new WebClient()) 
     { 
      Stopwatch watch = Stopwatch.StartNew(); 
      var data = client.DownloadData("http://news.bbc.co.uk"); 
      watch.Start(); 
      Console.WriteLine("{0} ms", watch.ElapsedMilliseconds); 
     } 
    } 
} 

Печатает 880 мс на моем ПК.

0

Всякий раз, когда вы измеряете что-либо, вы должны учитывать затраты на запуск. Если ваш .net-код находится в одном процессе, и вы измеряете только один запрос, то ваши измерения будут испорчены первоначальными затратами на инициализацию сборок, типов и т. Д.

Как Дарин и другие предложили вам должен убедиться, что:

1) Вы не используете этот процесс под управлением отладки. 2) Вы учитываете затраты на запуск.

Один из способов, которым вы можете сделать # 2, состоит в том, чтобы сделать два запроса и только измерить второй. Или вы можете сделать N запросов, отбросить 1-й и получить среднее число последних запросов N-1. Также убедитесь, что вы прочитали поток сущности.

2

При первом запросе страницы, .net пытается определить настройки прокси-сервера. Решение состоит в том, чтобы передать пустой объект WebProxy. Таким образом, он просто подключается к удаленному серверу вместо автоматического определения прокси-сервера. Ответ

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriTest); 
request.Proxy = new WebProxy(); 
0

Markos' работал отлично для меня по тому же вопросу:

request.Proxy = new WebProxy(); 

Уменьшенный запрос 16-секундный менее чем за секунду. Благодаря!