ASP.NET MVC 4 Webアプリケーションでの非同期スレッドのパフォーマンスには、数のプロセッサが発生しますか?

StackOverflow https://stackoverflow.com/questions/8390034

質問

私は非同期プログラミングが得意ではないので、質問は低いレベルにあるかもしれません。

ASP.NET MVC 4 DEVのASYNC CTPを使用して、以下のように非同期メソッドを作成しました。プレビュー:

public class Movie
{
    public string Title { get; set; }
    public string Url { get; set; }
    public string BoxArtUrl { get; set; }
}

public class MovieM {

    public IEnumerable<Movie> M2009 { get; set; }
    public IEnumerable<Movie> M2010 { get; set; }
    public IEnumerable<Movie> M2011 { get; set; }
}

public class HomeController : AsyncController  {

    public async Task<ActionResult> GetMoviesM()  {

        var profiler = MiniProfiler.Current; // it's ok if this is null

        var pageSize = 1000;
        var imageCount = 0;

        using (profiler.Step("Start pulling data (Async) and return it")) { 

            var m2009 = await QueryMoviesAsync(2009, imageCount, pageSize);
            var m2010 = await QueryMoviesAsync(2010, imageCount, pageSize);
            var m2011 = await QueryMoviesAsync(2011, imageCount, pageSize);

            return View(new MovieM { 
                M2009 = m2009,
                M2010 = m2010,
                M2011 = m2011
            });
        }
    }

    XNamespace xa = "http://www.w3.org/2005/Atom";
    XNamespace xd = "http://schemas.microsoft.com/ado/2007/08/dataservices";
    XNamespace xm = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";

    string query = "http://odata.netflix.com/Catalog/Titles?$filter=ReleaseYear eq {0}&$skip={1}&$top={2}&$select=Url,BoxArt";

    async Task<IEnumerable<Movie>> QueryMoviesAsync(int year, int first, int count)  {

        var client = new WebClient();
        var url = String.Format(query, year, first, count);
        var data = await client.DownloadStringTaskAsync(new Uri(url));
        var movies =
            from entry in XDocument.Parse(data).Descendants(xa + "entry")
            let properties = entry.Element(xm + "properties")
            select new Movie
            {
                Title = (string)entry.Element(xa + "title"),
                Url = (string)properties.Element(xd + "Url"),
                BoxArtUrl = (string)properties.Element(xd + "BoxArt").Element(xd + "LargeUrl")
            };
        return movies.AsEnumerable();
    }
}

コードは正常に機能します。デスクトップアプリ(たとえばWPFアプリ)で同じ関数を実行すると、有形のパフォーマンスの違いがわかります。 UIはブロックされておらず、データが利用可能になったときに即座にスクリーニングするようにプッシュされています。

しかし、Webアプリケーションでは、違いは本当にわかりません。また、同期と同じ関数を作成しましたが、どちらもほぼ同じです。

私が知りたいのはそれです:

  1. このアプリを持っているマシンで実行します Intel Core 2 Duo CPU T5750 2.00GHz. 。プロセッサの数は、C#に対する非同期スレッドのパフォーマンスに影響しますか?
  2. 私はここでWebアプリケーションの観点から何か間違ったことをしていますか?
役に立ちましたか?

解決

デスクトップアプリ(たとえばWPFアプリ)で同じ関数を実行すると、有形のパフォーマンスの違いがわかります。 UIはブロックされておらず、データが利用可能になったときに即座にスクリーニングするようにプッシュされています。

これは一般的な誤解です。投稿した方法は少しです もっとゆっくり 同期等価よりも、しかしUIアプリではもっと 応答性, 、 したがって 表示されます よりパフォーマンス。

ASP.NETシナリオでは、すべての非同期リクエストが完了した場合にのみページがレンダリングされます。それがあなたが違いを見ない理由です。

うまくいくよ 実際に リクエストを並列化することにより、よりパフォーマンスを発揮します。

var m2009Task = QueryMoviesAsync(2009, imageCount, pageSize);
var m2010Task = QueryMoviesAsync(2010, imageCount, pageSize);
var m2011Task = QueryMoviesAsync(2011, imageCount, pageSize);
await Task.WhenAll(m2009Task, m2010Task, m2011Task);
var m2009 = await m2009Task;
var m2010 = await m2010Task;
var m2011 = await m2011Task;

これにより、デスクトップとASP.NETの両方のパフォーマンスが向上します。

元のコードはシリアル構成を使用します(1つ await 一度に)。この場合、コードは非同期に実行されていますが、リクエストはより速く完了していません。使用することにはまだ利点があります async/await このように:リクエストはASP.NETスレッドを縛られていないため、サービスはさらにスケールアップできます。 UIの世界では、UIスレッドが縛られていないため、より応答します。しかし、ASP.NETとUIの両方について、 合計 の時間 完了 GetMoviesM メソッドはそれを作成しても削減されません async.

平行構成(使用 Task.WhenAll また Task.WhenAny)許可します GetMoviesM 全体として、並行してリクエストを行うため、より速く実行します。さらに、上記のスレッドメリットが得られます。

この場合、プロセッサの数は重要ではありません。スレッドプールで処理を行っているときにのみ機能します(例: Task.Run)、i/oを行うときではありません。 (これは単純化ですが、十分に真実です)。

他のヒント

いくつかのコメント。

まず、WebClientはデフォルトでは、セッションごとにサーバーごとに2つの接続のみを開きます。これは明らかにあなたのスケーリング能力に影響を与えるので、あなたはそれを変えたいかもしれません[参照してください WebClientの2つの接続制限をプログラムで削除するにはどうすればよいですか ]

第二に、コントローラー法とQueryMoviesAsyncメソッドの両方でASYNCを使用することに利点があるかどうかはわかりません。

第三に、WebClientはIDISPOSABLEを実装するため、使用(..)ステートメントで使用する必要があります。そうしないと、スケーラビリティにも影響する可能性があります。

上記のすべての変更を考慮して、元の質問に答えるために、はい、それがASP.net/iisのデフォルトであるため、実行時に複数のプロセッサ/コアを拡大する必要があります

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top