7

最近、ASP.NET MVC1 から ASP.NET MVC4 rc1 にアップグレードしたアプリケーションがあります。

Webforms ビューエンジンを使用します。

Url.Action(action,controller) が使用されるたびに、パフォーマンスの問題が発生します。

ASP.NET MVC3 で問題を再現できます。

ASP.NET MVC1 で Url.Action ヘルパーの 10 個のインスタンスを含むビューをレンダリングするには 3 ミリ秒、ASP.NET MVC3 で同じものをレンダリングするには 40 ミリ秒が必要です。

レンダリングを高速化する方法をいくつか見つけました。

  • デフォルトルートを一番上に移動しました

  • Url.Action を削除し、静的リンクを使用しました

これは正しくありません。アプリケーションはかなり大きく、適切に機能する適切なルーティングが必要です。また、すべてのパフォーマンスのボトルネックを見つけたという自信もありません。ルーティングは MVC の中心的な部分です。パフォーマンスが悪いものがあると、アプリケーションのさまざまな部分に表示されます。

MVC3 がいくつかのルーティング機能 (正規表現の制約など) を導入したという印象を受けました。これらの機能を使用しなくても、アプリケーションのパフォーマンスが低下する可能性があります。

ルーティングの機能を変更したり、別の URL ヘルパー セットを使用したりするなど、できることはありますか?

このコードは問題を再現します:

インデックス アクション

public ActionResult Index()
        {

            return View();
        }

インデックス.aspx

<%@ Page Language="C#"  Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head >
    <title></title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

<body>
    <div class="page">
<%= Url.Action("Action1", "Controller1") %>
<%= Url.Action("Action2", "Controller2") %>
<%= Url.Action("Action3", "Controller3") %>
<%= Url.Action("Action4", "Controller4") %>
<%= Url.Action("Action5", "Controller5") %>
<%= Url.Action("Action6", "Controller6") %>
<%= Url.Action("Action7", "Controller7") %>
<%= Url.Action("Action8", "Controller8") %>
<%= Url.Action("Action9", "Controller9") %>
<%= Url.Action("Action10", "Controller10") %>
    </div>
</body>
</html>

ルート登録 これは奇妙に見えますが、あまり複雑ではないルーティングをシミュレートしたいだけです。これはSOの600ルートではありません!

public static void RegisterRoutesSlow(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.IgnoreRoute("{language}/Content/{*pathInfo}");

    routes.IgnoreRoute("images/{*pathinfo}");
    routes.IgnoreRoute("scripts/{*pathinfo}");
    routes.IgnoreRoute("content/{*pathinfo}");
    routes.IgnoreRoute("{file}.gif");
    routes.IgnoreRoute("{file}.jpg");
    routes.IgnoreRoute("{file}.js");
    routes.IgnoreRoute("{file}.css");
    routes.IgnoreRoute("{file}.png");
    routes.IgnoreRoute("{file}.pdf");
    routes.IgnoreRoute("{file}.htm");
    routes.IgnoreRoute("{file}.html");
    routes.IgnoreRoute("{file}.swf");
    routes.IgnoreRoute("{file}.txt");
    routes.IgnoreRoute("{file}.xml");
    routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });

    for (int i = 0; i <= 10; i++)
    {
        routes.MapRoute(
            // Route name
            "RouteName" + i.ToString(),
            // URL with parameters                              
            "{language}/{controller}/{action}/{para1}",
            // Parameter defaults
            new
            {
                action = "Index",
                language = "de",
                para1 = 0
            },
            //Parameter constraints
            new { language = "de|en", controller = "SomeNameOfAnActualController" + i.ToString() }
            );
    }
    routes.MapRoute(
                   "DefaulRoute",            // Route name
                   "{controller}/{action}",    // URL with parameters
                   new
                   {
                       controller = "Home",
                       action = "Index",
                   }
               );
    routes.MapRoute("404-PageNotFound", "{*url}", new { controller = "Error", action = "PageNotFound", language = "de" });
}

編集

サンプル コードは MVC2 に対してコンパイルされました。VS2010 では、MVC2 を .NET 3.5 または 4.0 に対してコンパイルできます。

3.5 でのパフォーマンスは良好で、4.0 でのパフォーマンスは悪くなります。

これは、パフォーマンスの低い部分が MVC アセンブリではなく、フレームワーク アセンブリ (System.Web.Routing.dll など) にあることを意味していると思います。質問は同じです。それについて何かできることはありますか? 次のような回答も受け入れられます: いいえ、バージョン 3.5 から 4.0 で MS が XXX を変更したため、コードが遅いです。

編集-2

System.Web.Routing.dll の時間がかかる部分を逆コンパイルしました。コンパイルされた正規表現を使用します。正規表現を実行せずに戻るコード パス (constraint2.Match) がありますが、別の高価な操作を内部で使用しているかどうかはまだ確認していません。

protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
    object obj2;
    IRouteConstraint constraint2 = constraint as IRouteConstraint;
    if (constraint2 != null)
    {
        return constraint2.Match(httpContext, this, parameterName, values, routeDirection);
    }
    string str = constraint as string;
    if (str == null)
    {
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("Route_ValidationMustBeStringOrCustomConstraint"), new object[] { parameterName, this.Url }));
    }
    values.TryGetValue(parameterName, out obj2);
    string input = Convert.ToString(obj2, CultureInfo.InvariantCulture);
    string pattern = "^(" + str + ")$";
    return Regex.IsMatch(input, pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
4

3 に答える 3

3

あなたに似た解決された問題があります:ページ上の Url.Action への最初の呼び出しが 遅いです。非常に遅い正規表現制約によるルーティング制約に関する結論があります。

于 2012-08-17T21:56:43.667 に答える
0

表示されている原因はわかりませんが、MVC1とMVC4だけでなく、それ以降のバージョンでのIISセットアップがビューレンダリングの速度に影響を与える可能性があります。数か月前、MVC 3アプリのパフォーマンス向上のヒントに関して、非常に興味深いと思ったスライドデッキに出くわしました。

http://www.slideshare.net/ardalis/improving-aspnet-mvc-application-performance

具体的には、次のように記載されているスライド28をご覧ください。

IISUrlRewriteモジュールをアンインストールします

  • サーバー上のアプリケーションがそれを使用していない場合
  • v3より前のMVCアプリでは効果がありません
  • URL生成の速度を向上させます

これは、UrlRewriteモジュールがMVC 3に悪影響を与えるが、MVC 2または1には悪影響を与えないことを意味すると解釈します。これは、表示されている速度低下の原因となる可能性があります。他にもいくつかの改善点がありますが、それらのいずれも「直接」あなたが見ているものに関連しているとは思いません。

于 2012-08-14T13:56:23.867 に答える
0

各ビューは、最初に使用されるときにコンパイルされ、キャッシュされます。ただし、aspx ビューは Mvc 専用に設計されていないため、各 Url.Action は最終リンクで一度にコンパイルされるのではなく、実行ごとに再計算されます。Razor コンパイラの最適化が向上しました。唯一の解決策は、Url.Action を使用してさまざまなリンクを計算し、それらをアプリケーション レベルのプロパティに格納することです。これにより、最初の実行時に計算されます。これらは、アプリケーション ディクショナリまたはクラスの静的プロパティに配置できます。

于 2012-08-14T08:17:56.177 に答える