ASP.NET MVC производительность генерации URL - PullRequest
15 голосов
/ 17 октября 2008

Небольшой тест с ASP.NET MVC. Код страницы просмотра:

    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,112 мс на URL составляет около 4 мс чистой загрузки процессора.

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

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

Есть ли другие рабочие сайты в ASP.NET MVC с проблемами производительности или полезными советами?

Ответы [ 4 ]

4 голосов
/ 19 октября 2008

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

Должность

Ответ

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

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

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

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

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

1 голос
/ 17 октября 2008

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

<%= 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 мс на ссылку

Гораздо лучшая производительность благодаря более неприятному коду. Жаль.

1 голос
/ 17 октября 2008

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

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

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

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

0 голосов
/ 17 октября 2008

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

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

...