Производительность URL-адреса ASP.NET MVC

Небольшой ориентир с ASP.NET MVC. Код Viewpage:

    public string Bechmark(Func<string> url)
    {
        var s = new Stopwatch();
        var n = 1000;

        s.Reset();
        s.Start();
        for (int i = 0; i < n; i++)
        {
            var u = url();
        }
        s.Stop();
        return s.ElapsedMilliseconds + " ms, " + ((s.ElapsedMilliseconds) / (float)n) + " ms per link<br/>";
    }

Просмотр кода:

<%= Bechmark(() => Url.Action("Login", "Account")) %>

<%= Bechmark(() => Url.Action("Login", "Account", new {username="bla", password="bla2", returnurl="blabla32", rememberme=false} )) %>

<%= Bechmark(() => Html.BuildUrlFromExpression<AccountController>(a=>a.ChangePassword("bla", "bla", "ya")) ) %>

Выполнение этого на типичном ноутбуке Core2 по шаблону нового проекта по умолчанию с помощью ASP.NET MVC Beta дает следующие результаты:

38 мс, 0,038 мс на канал

120 мс, 0,12 мс на канал

54 мс, 0,054 мс на канал

Запуск того же теста в производственном проекте с примерно 10 контроллерами, которые имеют всего около 100 методов и 30 записей таблицы маршрутизации, производительность сильно ухудшает метод на основе выражений:

31 мс, 0,031 мс на канал

112 мс, 0,112 мс на канал

450 мс, 0,45 мс на канал

Мы довольно часто используем этот метод (ремонтопригодность) и выполняем бенчмаркинг производительности, что значительно ухудшает производительность сайта - страницы быстро содержат около 30 или более таких ссылок, что означает 10 мс дополнительных накладных расходов на одной странице. Даже 0.112ms за URL-адрес составляет около 4 мс чистых затрат на процессор.

Следует отметить, что производительность всех трех вызовов генерации URL-адресов между MVC Preview 3 и Beta (выпущенная вчера) улучшилась в 5 раз.

Переполнение стека, предположительно, поддерживается той же структурой, как вы, ребята, решили эту проблему масштабирования? Либеральное кэширование первой страницы (множество ссылок) и предварительно обработанных элементов управления?

Любые другие производственные сайты в ASP.NET MVC с проблемами производительности или некоторыми хорошими советами?

Ответы

Ответ 1

Я задал этот вопрос на форумах MS, которые получили ответ от разработчика MS MVC.

Сообщение

Ответ

От MVC Preview 2 до недавно выпущенной бета-версии MVC со вчерашнего дня было много изменений в маршрутизации. Некоторые из этих изменений включают повышение производительности. Вот несколько трюков, чтобы сделать создание URL более эффективным в вашем приложении:

  • Использовать именованные маршруты. Именованные маршруты являются необязательной функцией маршрутизации. Имена применяются только к генерации URL-адресов - они никогда не используются для сопоставления входящих URL-адресов. Когда вы указываете имя при создании URL-адреса, мы будем пытаться только сопоставить этот маршрут. Это означает, что даже если указанный вами маршрут указан на 100-м маршруте в таблице маршрутов, мы перейдем прямо к нему и попытаемся соответствовать.

  • Поместите наиболее распространенные маршруты в начале таблицы маршрутов. Это улучшит производительность как генерации URL-адресов, так и обработки входящих URL-адресов. Маршрутизация работает на основе правила, которое выигрывает первый матч. Если первое совпадение - это 100-й маршрут в таблице маршрутов, то это означает, что он должен был попробовать 99 других маршрутов, и ни один из них не соответствовал.

  • Не используйте URL-адреса. Некоторым это нравится, некоторые люди этого не делают. Это немного сложно освоить. Приятно использовать, если ваши URL-адреса очень динамичны, но это может быть немного хлопот, когда у вас очень мало URL-адресов, и, возможно, вам все равно, как они выглядят.

Моим любимым вариантом является # 1, так как он очень прост в использовании, а также делает создание URL более детерминированным с точки зрения разработчика приложений (это вы!).

Ответ 2

Кэширование ссылок, вероятно, будет хорошим предложением для команды, поскольку они не изменятся для жизни процесса (для большинства приложений в любом случае).

Пока вы не начнете определять свои маршруты в настраиваемой форме (например, web.config или в базе данных), вам придется немного поменять размер.

Я подозреваю, что большая часть задержки на среднем примере - это анонимный тип, который автоматически преобразуется в словарь. Кэширование URL-адреса не поможет здесь b/c, вам все равно придется отражать этот тип.

Тем временем вы можете создать свои собственные вспомогательные методы для некоторых из этих словарных ссылок, которые требуют точного ввода, который вам нужен. Затем вы можете самостоятельно обработать кэширование.

Ответ 3

Хорошо, две дополнительные метрики в проекте пустого шаблона:

<%= Bechmark(() => Url.Action("Login", "Account", new Dictionary<string, object> {{"username", "bla"}, {"password", "bla2"}, {"returnurl", "blabla32"}, {"rememberme", "false"}})) %>

<%= Bechmark(() => Url.Action("Login", "Account", new RouteValueDictionary(new Dictionary<string, object> {{"username", "bla"}, {"password", "bla2"}, {"returnurl", "blabla32"}, {"rememberme", "false"}}))) %>

Результаты:

71 мс, 0,071 мс на канал

35 мс, 0,035 мс на канал

Значительно лучше работать с более неприятным кодом. Слишком плохо.

Ответ 4

Кэширование ссылок, вероятно, будет хорошим предложение для команды, поскольку они не будут изменение для жизни процесса (для большинства приложений в любом случае).

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