.NET скорость HttpWebRequest по сравнению с браузером

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

Если я использую 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();
9
задан Chris 12 January 2010 в 01:38
поделиться

7 ответов

Запустите приложение с 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 мс на моем компьютере.

1
ответ дан 3 November 2019 в 03:47
поделиться

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

1
ответ дан 3 November 2019 в 03:47
поделиться

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

Что случится, если вставить '/' в конец URL?

.
1
ответ дан 3 November 2019 в 03:47
поделиться

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

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

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

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

0
ответ дан 3 November 2019 в 03:47
поделиться

Похоже, что копия только обрабатывает отдельные файлы . Вот функция для рекурсивного копирования я нашел в этой заметке на странице копирования документации :

<?php 
function recurse_copy($src,$dst) { 
    $dir = opendir($src); 
    @mkdir($dst); 
    while(false !== ( $file = readdir($dir)) ) { 
        if (( $file != '.' ) && ( $file != '..' )) { 
            if ( is_dir($src . '/' . $file) ) { 
                recurse_copy($src . '/' . $file,$dst . '/' . $file); 
            } 
            else { 
                copy($src . '/' . $file,$dst . '/' . $file); 
            } 
        } 
    } 
    closedir($dir); 
} 
?>
-121--3473510-

Спасибо за ответы. Я чувствую, что каждый ответ был частью ответа. Вот что я искал. Символ

  1. ? является просто кратким для (something 'start) . Таким образом, (a 'start) можно переписать как a? . Таким образом, пример становится:

     b * (abb *) * a?
    

    В питоне мы бы написали:

     p = re.compile (r '^ b * (abb *) * a? $')
    
  2. Прямая трансляция синтаксиса регулярного регулярного выражения в python (т.е. копирование и вставка) не работает, потому что python соответствует самой короткой подстроке (если символы $ или ^ отсутствуют), в то время как теоретические регулярные выражения соответствуют самой длинной начальной подстроке .
    Так, например, если у нас была последовательность:

     s = 'aa'
    

    Наш учебник regex b * (abb *) * a? не будет соответствовать ему, потому что он имеет два а. Однако если скопировать его прямо в python:

     > > p = re.compile (r 'b * (abb *) * a?')
    > > bool (p.match (s))
    Правда
    

    Это происходит потому, что наш регекс соответствует только подстроке «a» нашей последовательности «aa».
    Для того, чтобы сказать Питону, чтобы сделать совпадение в целом ряде мы должны сказать ему, где начало и конец последовательности, с ^ и $ соответственно:

     > > p = re.compile (r '^ b * (abb *) * a? $')
    > > bool (p.match (s))
    Ложный
    

    Обратите внимание, что python regex match () совпадает с началом последовательностей, поэтому он автоматически принимает ^ в начале. Однако функция search () не выполняет, и поэтому мы сохраняем ^ .
    Так например:

     > > s = 'aa'
    > > p = re.compile (r 'b * (abb *) * a? $')
    > > bool (p.match (s))
    Ложь # Правильно
    > > bool (p.search (s))
    True # Неверно - поиск проигнорировал первый «» а
    
-121--4594708-

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

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

Есть несколько причин, которые могут быть вызваны:

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

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

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

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

2
ответ дан 3 November 2019 в 03:47
поделиться

Какова поломка этого 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 мс

Fiddler: В целом истекает: 00:00: 00.0620000

1
ответ дан 3 November 2019 в 03:47
поделиться

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

0
ответ дан 3 November 2019 в 03:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: