6

かなり単純なASP.MVCビューでパフォーマンスの問題が発生します。

これは、ほぼ瞬時に実行されるはずのログオンページですが、約0.5秒かかります。

多くの掘り下げの後、問題は最初の呼び出しであるように見えますUrl.Action-それは約450msかかります(MiniProfilerによるとが、それはめちゃくちゃ遅いようです。

の後続の呼び出しUrl.Actionは1ミリ秒未満かかります。これは、私が期待するものとより一致しています。

これは、使用するか使用するかにかかわらず一貫Url.Action("action", "controller")していますUrl.Action("action")が、を使用すると発生しないようですUrl.Content("~/controller/action")。これは、を呼び出すときにも発生しますHtml.BeginForm("action")

誰かがこれを引き起こしているものを知っていますか?

ソースを掘り下げるRouteCollection.GetVirtualPathと、との両方に共通しているため、それが原因である可能性がありUrl.ActionますHtml.BeginForm。しかし、確かにそれは至る所で使用されていますか?つまり、1/2秒は遅すぎます。

私は20かそこらのカスタムルートを持っています(それはいくつかのレガシーWebFormsページを備えたかなり大きなアプリです)が、それでも時間が遅すぎるようです。

それを修正する方法はありますか?

4

4 に答える 4

5

問題が見つかりました。ルーティングテーブルに問題があります(キリルを応援します)。

基本的に、次のようなルートがたくさんあります。

string[] controllers = GetListOfValidControllers();

routes.MapRoute(
    name: GetRouteName(),
    url: subfolder + "/{controller}/{action}/{id}",
    defaults: new { action = "Index", id = UrlParameter.Optional },
    constraints: new { controller = "(" + string.Join("|", controllers) + ")" });

正規表現のチェックは非常に遅く、痛々しいほど遅いことがわかりました。IRouteConstraintそこで、代わりにチェックするだけの実装に置き換えましたHashSet

次に、マップルートの呼び出しを変更しました。

routes.MapRoute(
    name: GetRouteName(),
    url: subfolder + "/{controller}/{action}/{id}",
    defaults: new { action = "Index", id = UrlParameter.Optional },
    constraints: new { controller = new HashSetConstraint(controllers) });

また、リンクされた記事で言及されているRegexConstraintを、このような多くの呼び出しを含む、より複雑なものにも使用しました(従来のWebFormページがあるため)。

routes.IgnoreRoute(
    url: "{*allaspx}", 
    constraints: new { allaspx = new RegexConstraint( @".*\.as[pmh]x(/.*)?") });

これらの2つの簡単な変更により、問題は完全に修正されます。Url.ActionそしてHtml.BeginForm今ではごくわずかな時間しかかかりません(ルートがたくさんある場合でも)。

于 2012-08-13T15:50:12.923 に答える
1

あなたの問題はビューのコンパイルにあるように私には思えます。ビルド時にビューをプリコンパイルする必要があり、この問題はなくなります。 詳細はこちら

于 2012-08-10T11:59:50.903 に答える
1
    public class RegexConstraint : IRouteConstraint, IEquatable<RegexConstraint>
     {
    Regex regex;
    string pattern;

    public RegexConstraint(string pattern, RegexOptions options = RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase)
    {
        regex = new Regex(pattern, options);
        this.pattern = pattern;
    }

    public bool Match(System.Web.HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        object val;
        values.TryGetValue(parameterName, out val);
        string input = Convert.ToString(val, CultureInfo.InvariantCulture);
        return regex.IsMatch(input);
    }

    public string Pattern
    {
        get
        {
            return pattern;
        }
    }

    public RegexOptions RegexOptions
    {
        get
        {
            return regex.Options;
        }
    }

    private string Key
    {
        get
        {
            return regex.Options.ToString() + " | " + pattern;
        }
    }

    public override int GetHashCode()
    {
        return Key.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        var other = obj as RegexConstraint;
        if (other == null) return false;
        return Key == other.Key;
    }

    public bool Equals(RegexConstraint other)
    {
        return this.Equals((object)other);
    }

    public override string ToString()
    {
        return "RegexConstraint (" + Pattern + ")";
    }
}
于 2012-09-12T08:49:09.310 に答える
0

私はそれを「必要最低限​​」に取り除いた...単一のファイルをメモリに設定し、IHttpModuleからダウンロードするのと比較してアクションからダウンロードする。IHttpModuleは、何らかの理由(おそらく、MVCパイプラインのロード、ルーティング)のために(製品リストイメージなどの小さなファイルの場合)はるかに高速です。ルーティングで使用される正規表現はありません(これにより、さらに遅くなります)。IHttpModuleでは、URLがドライブ上のファイルを指している場合と同じ速度に到達しています(もちろん、ファイルがドライブ上にあるが、URLが指すドライブの場所にはない場合)。

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
     <add name="ImagesHandler" type="NsdMupWeb.ImagesHttpModule" />
  </modules>
</system.webServer>


//Code is made for testing
public class ImagesHttpModule : IHttpModule
{
    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        context.BeginRequest += Context_BeginRequest;
    }

    private void Context_BeginRequest(object sender, EventArgs e)
    {
        var app = (HttpApplication)sender;
        if (app.Request.CurrentExecutionFilePathExtension.Length > 0)
        {
            var imagePathFormated = "/image/";
            var imagesPath = app.Request.ApplicationPath.TrimEnd('/') + imagePathFormated;
            if (app.Request.CurrentExecutionFilePath.StartsWith(imagesPath))
            {
                var path = app.Request.CurrentExecutionFilePath.Remove(0, imagesPath.Length);
                var parts = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length > 1)
                {
                    var ms = new MemoryStream();
                    Stream stream;

                    stream = System.IO.File.OpenRead(@"C:\Programming\Sindikat\Main\NsdMupWeb\Files\Cached\imageFormatProductList\1b1e2671-a365-4a87-97ba-063cf51ac34e.jpg");
                    var ctx = ((HttpApplication)sender).Context;
                    ctx.Response.ContentType = MimeMapping.GetMimeMapping(parts[1]);
                    ctx.Response.Headers.Add("last-modified", new DateTime(2000, 01, 01).ToUniversalTime().ToString("R"));

                    byte[] buffer = new byte[stream.Length / 2];
                    stream.Read(buffer, 0, buffer.Length);
                    ctx.Response.BinaryWrite(buffer);

                    buffer = new byte[stream.Length - buffer.Length];
                    stream.Read(buffer, 0, buffer.Length);
                    ctx.Response.BinaryWrite(buffer);
                    ctx.Response.End();
                }
            }
        }
    }
}
于 2019-12-05T21:59:16.817 に答える