高パフォーマンス ASP.NET アプリケーションの開発

このトピックのガイドラインでは、ASP.NET Web アプリケーションの最大スループットを実現できるテクニックを示します。ガイドラインは次のセクションに分けられます。

  • ページ コントロールおよびサーバー コントロールの処理

  • 状態管理

  • データ アクセス

  • Web アプリケーション

  • コーディングの技法

ページ コントロールおよびサーバー コントロールの処理

次のガイドラインでは、ASP.NET のページおよびコントロールを効率的に使用するための推奨方法を示します。

  • サーバーへの不要なラウンド トリップは避ける。   ASP.NET サーバー コントロールの使用およびポストバック イベント処理の実行が不要な場合があります。たとえば、ASP.NET Web ページでのユーザー入力の検証は、そのデータをサーバーに送信する前にクライアント上で実行できます。一般に、検証またはデータ ストアへの書き込みを行うために情報をサーバーに送信する必要がない場合は、サーバーへのラウンド トリップを実行するコードを使用しないことにより、ページのパフォーマンスおよびユーザーの操作性を向上できます。また、フル ラウンド トリップを実行する代わりにクライアント コールバックを使用して、サーバーからデータを読み取ることもできます。詳細については、「ASP.NET Web ページでポストバックせずにプログラムによってクライアント コールバックを実装する」を参照してください。

    カスタムのサーバー コントロールを開発する場合は、ECMAScript (JavaScript) をサポートするブラウザ用のクライアント側コードをそれらのコントロールで生成することを検討します。そのようにサーバー コントロールを使用することによって、情報が Web サーバーに送信される回数を大幅に減少させることができます。詳細については、「ASP.NET カスタム サーバー コントロールの開発」を参照してください。

  • ページ オブジェクトの IsPostBack プロパティを使用し、ラウンド トリップの処理が不必要に実行されないようにする。   サーバー コントロールのポストバック処理を実行するコードを記述するときに、ポストバックごとにではなく、ページが最初に要求されたときにのみコードを実行するようにしたい場合があります。サーバー コントロールのイベントに対する応答としてページが生成されるかどうかに応じて、条件付きでコードを実行する場合は、IsPostBack プロパティを使用します。

  • **サーバー コントロールのビューステートは必要な場合にだけ保存する。**自動ビューステート管理を使用すると、サーバー コントロールはラウンド トリップ時にプロパティ値を再設定できるため、コードを記述する必要がありません。ただし、この機能は、サーバー コントロールのビューステートがサーバーとの間で非表示のフォーム フィールドとして送受信されるため、パフォーマンスに影響を及ぼします。どのようなときにビューステートが役に立ち、どのようなときにページのパフォーマンスの妨げになるのかを理解することは有用です。たとえば、ラウンド トリップごとにサーバー コントロールをデータにバインドする場合、コントロールの値はデータ バインディング中に新しい値で置換されるため、保存されたビューステートは使用されません。この場合は、ビューステートを無効にすることで処理時間を短縮し、ページ サイズを削減できます。

    ビューステートは既定ですべてのサーバー コントロールについて有効になっています。ビューステートを無効にするには、次の DataGrid サーバー コントロールの例に示すように、コントロールの EnableViewState プロパティを false に設定します。

    <asp:datagrid EnableViewState="false" datasource="..." 
       runat="server"/>
    

    ページ全体にわたってビューステートを無効化する場合は @ Page ディレクティブを使用できます。この方法は、ページからサーバーへのポストバックを実行しない場合に便利です。

    <%@ Page EnableViewState="false" %>
    
    メモ :

    ユーザー コントロールについてビューステートを有効にするかどうかを指定する EnableViewState 属性は、@ Control ディレクティブでもサポートされます。

    ページのサーバー コントロールで使用するビューステートのサイズを分析するには、trace="true" 属性を @ Page ディレクティブに含め、ページのトレースを有効にします。トレース出力で、[コントロールのツリー] テーブルの [Viewstate] 列を確認します。トレースおよびトレースを有効化する方法については、「ASP.NET トレースの概要」を参照してください。

  • **特別な理由がない限りバッファリングはオンにしておく。**ASP.NET Web ページのバッファリングを無効にすると、パフォーマンスが大幅に低下します。詳細については、Buffer プロパティを参照してください。

  • 高速な前方向データ カーソルには、 Transfer Server Server オブジェクトの Transfer **メソッドを使用するか、またはページ間ポスティングを使用して、同一アプリケーション内の ASP.NET ページ間でリダイレクトする。**詳細については、「ユーザーをほかのページへリダイレクトする」を参照してください。

状態管理

次のガイドラインでは、状態管理の効率化を図るための推奨方法を示します。

  • **セッション状態は使用しないときは無効にする。**すべてのアプリケーションやページで、ユーザーごとのセッション状態が必要なわけではありません。セッション状態が不要な場合は無効にします。セッション状態をページに対して無効にするには、次の例に示すように、@ Page ディレクティブの EnableSessionState 属性を false に設定します。

    <%@ Page EnableSessionState="false" %>
    
    メモ :

    セッション変数にアクセスする必要のあるページがあっても、そのページがセッション変数の作成または修正を行わない場合は、@ Page ディレクティブの EnableSessionState 属性を ReadOnly に設定しておきます。

    セッション状態は、XML Web サービス メソッドに対しても無効にできます。詳細については、「ASP.NET と XML Web サービス クライアントを使用して作成した XML Web サービス」を参照してください。

    セッション状態をアプリケーションに対して無効にするには、次の例に示すように、アプリケーションの Web.config ファイルの SessionState セクションで、Mode 属性を Off に設定します。

    <sessionState mode="Off" />
    
  • アプリケーションに必要な適切なセッション状態プロバイダを選択する。   ASP.NET では、インプロセス セッション状態、Windows サービスのアウトプロセス セッション状態、SQL Server データベースのアウトプロセス セッション状態の複数の方法で、アプリケーションのセッション データを格納できます (カスタム セッション状態プロバイダを作成し、選択したデータ ストアにセッション データを格納することもできます)。それぞれにメリットがありますが、速さという点では、インプロセス セッション状態が一番の方法です。少量の揮発性データをセッション状態に格納するだけであれば、インプロセス プロバイダの使用をお勧めします。アウトプロセス セッション状態のオプションが有効なのは、複数のプロセッサまたは複数のコンピュータにわたってアプリケーションがスケールアップされる場合や、サーバーやプロセスが再起動されてもセッション データを保持する場合です。詳細については、「ASP.NET のセッション状態」を参照してください。

データ アクセス

次のガイドラインでは、アプリケーションのデータ アクセスの効率化を図るための推奨方法を示します。

  • データ アクセスには SQL Server およびストアド プロシージャを使用する。.NET Framework に用意されているデータ アクセス メソッドの場合、高パフォーマンスでスケーラブルな Web アプリケーションを作成するには、データ アクセス用に SQL Server を使用することをお勧めします。マネージ SQL Server プロバイダを使用する場合は、可能な場合は SQL コマンドの代わりにコンパイル済みストアド プロシージャを使用すると、さらにパフォーマンスを向上させることができます。SQL Server ストアド プロシージャの使用方法の詳細については、「パラメータの構成 (ADO.NET)」を参照してください。

  • SqlDataReader クラスを使用する。   SqlDataReader クラスは、SQL Server データベースから取得される前方向のデータ ストリームを提供します。読み取り専用のストリームを ASP.NET アプリケーションで使用できる場合、SqlDataReader クラスは DataSet クラスよりも高いパフォーマンスを実現します。SqlDataReader クラスは、SQL Server のネイティブなネットワーク データ転送形式を使用してデータ接続から直接データを読み込みます。たとえば、SqlDataSource コントロールにバインドするときは、DataSourceMode プロパティを DataReader に設定することで、パフォーマンスを向上できます (データ リーダーを使用すると、一部の機能を使用できなくなります)。また、SqlDataReader クラスは IEnumerable インターフェイスも実装しているため、データをサーバー コントロールと連結することもできます。詳細については、SqlDataReader クラスを参照してください。ASP.NET がデータにアクセスする方法については、「ASP.NET でのデータ アクセス」を参照してください。

  • **可能な場合はデータおよびページ出力をキャッシュする。**ASP.NET には、ページ出力やデータをページ要求ごとに動的に計算する必要がない場合に、これらをキャッシュするための機構が用意されています。さらに、サイト内でトラフィックが特に集中することが想定される領域では、ページやデータの要求をキャッシュするようにデザインすることで、それらのページのパフォーマンスを最適化できます。キャッシュを適切に使用すると、.NET Framework の他の機能を使用する場合よりもサイトのパフォーマンスを向上できます。

    ASP.NET キャッシュを使用する場合には、以下の点に注意してください。1 つは、キャッシュする項目が多すぎないようにするということです。各項目をキャッシュすると、メモリが消費されます。簡単に計算できる項目やあまり使用されない項目はキャッシュしないでください。もう 1 つは、キャッシュする項目に短い有効期限を割り当てないということです。項目の有効期限がすぐに切れてしまうと、キャッシュ内で不必要な更新が行われ、クリーンアップ コードやガベージ コレクタの処理が増加します。項目の期限切れによるキャッシュの更新は、ASP.NET アプリケーションのパフォーマンス オブジェクトに関連付けられた Cache Total Turnover Rate パフォーマンス カウンタを使用して監視できます。特に有効期限前に項目が削除される場合は、高い回転率が問題となっている可能性があります (このような状態をメモリ圧迫と呼ぶこともあります)。

    ページ出力とデータの要求をキャッシュする方法については、「ASP.NET のキャッシュの概要」を参照してください。

  • **SQL キャッシュの依存関係を適切に使用する。   **ASP.NET では、使用している SQL Server のバージョンに従って、テーブル ベース ポーリングとクエリ通知の両方がサポートされています。テーブル ベース ポーリンクは、すべてのバージョンの SQL Server でサポートされています。テーブル ベース ポーリンク時に、テーブル内で変更が発生した場合、すべてのリスナが無効になります。これは、アプリケーション内に不要な処理が発生する原因になります。変更が頻繁にあるテーブルに対するテーブル ベース ポーリングはお勧めしません。たとえば、カタログ テーブルのような変更があまりされないテーブルに対して、テーブル ベース ポーリングをお勧めします。オーダー テーブルのような更新が頻繁にされるテーブルに対してはお勧めしません。クエリ通知は SQL Server 2005 でサポートされています。クエリ通知は特定のクエリをサポートし、これにより、テーブルの変更時に送信される通知数を削減できます。クエリ通知はテーブル ベース ポーリングよりパフォーマンスに優れていますが、何千ものクエリには対応できません。

    SQL キャッシュの依存関係の詳細については、「チュートリアル : SQL Server での ASP.NET の出力キャッシュの使用」または「SqlCacheDependency クラスによる ASP.NET のキャッシュ」を参照してください。

  • **UI (User Interface) ページングと並べ替えではなく、データ ソース ページングと並べ替えを使用する。   **DetailsViewGridView などのデータ コントロールの UI ページング機能は、ICollection インターフェイスをサポートするすべてのデータ ソース オブジェクトで使用できます。各ページング操作において、データ コントロールはデータ ソースに対してデータ コレクション全体を問い合わせ、表示する行を選択し、残りのデータは無視します。データ ソースが DataSourceView を実装し、CanPage プロパティが true を返す場合、データ コントロールは UI ページングの代わりにデータ ソース ページングを使用します。この場合、データ コントロールは、各ページング操作において必要な行のみ問い合わせます。そのため、データ ソース ページングは、UI ページングより効率的です。データ ソース ページングをサポートするのは ObjectDataSource データ ソース コントロールのみです。他のデータ ソース コントロールでデータ ソース ページングを有効にするには、そのデータ ソース コントロールを継承してから、その動作を変更する必要があります。

  • **イベント検証によるセキュリティ上の利点とそのパフォーマンス低下とのバランスを取る。   **System.Web.UI.WebControls クラスおよび System.Web.UI.HtmlControls クラスから派生したコントロールは、イベントが、そのコントロールによってレンダリングされたユーザー インターフェイスから発生したものかどうかを検証できます。これにより、コントロールがなりすましによるイベント通知に応答することを防ぐことができます。たとえば、DetailsView コントロールでは、このコントロールでもともとサポートされていない削除呼び出しによりデータを削除してしまわないように、この削除呼び出しの処理を禁止できます。この検証は多少のパフォーマンス低下の原因になります。この動作は、EnableEventValidation 構成要素と RegisterForEventValidation メソッドを使用して制御できます。検証によるパフォーマンスの低下の程度は、そのページ上にあるコントロールの数によりますが、数パーセントの範囲内です。

    セキュリティに関するメモ :

    イベント検証は無効にしないことを強くお勧めします。イベント検証を無効にする場合は、その前に、アプリケーションに意図しない影響を与える可能性があるポストバックが一切発生しないことを確認しておく必要があります。

  • **必要ない限り、ビューステートは暗号化しない。   **ビューステートの暗号化を行うことにより、非表示のビューステート フィールド内の値を読み取られないようにすることができます。典型的な例として、DataKeyNames プロパティに ID フィールドが格納される GridView コントロールがあります。ID フィールドは、レコードへの更新を調整するために必要です。この ID 情報を読み取られないようにするために、ビューステートを暗号化できます。ただし、暗号化には、その初期化時にパフォーマンスが一定量低下し、また暗号化の対象となるビューステートのサイズによっては、さらにパフォーマンスが低下します。暗号化はページの読み込みごとにセットアップされるので、ページが読み込まれるたびに同じだけのパフォーマンスへの影響が生じます。

  • **SqlDataSource のキャッシュ、並べ替え、およびフィルタ処理を使用する。   **SqlDataSource コントロールの DataSourceMode プロパティが DataSet に設定されている場合、SqlDataSource はクエリからの結果セットをキャッシュできます。このようにデータがキャッシュされた場合、このコントロールのフィルタ処理と並べ替えの操作 (FilterExpression プロパティと SortParameterName プロパティで構成) で、キャッシュされたデータが使用されます。多くの場合、データセット全体をキャッシュし、FilterExpression プロパティと SortParameterName プロパティを使用して並べ替えとフィルタ処理を行う場合、SQL クエリで WHERE 句や SORT BY 句を使って選択アクションごとにデータベースにアクセスするよりも、アプリケーションの実行速度は速くなります。

Web アプリケーション

次のガイドラインでは、Web アプリケーションの全体的な効率化を図るための推奨方法を示します。

  • プリコンパイルの検討   Web アプリケーションは、ASP.NET Web ページなどのリソースで最初の要求についてバッチ コンパイルが実行されます。アプリケーション内のページがコンパイルされていない場合、バッチ コンパイルはディレクトリ内のすべてのページをチャンク単位でコンパイルし、ディスクおよびメモリの使用率を向上させます。ASP.NET コンパイル ツール (Aspnet_compiler.exe) は、Web アプリケーションのプリコンパイルに使用できます。埋め込み先コンパイルの場合、コンパイル ツールは ASP.NET ランタイムを呼び出して、ユーザーが Web サイトのページを要求するときと同じように Web サイトをコンパイルします。UI のマークアップが保存されているため、Web アプリケーションをプリコンパイルできます。または、ソース コードを変更できないため、イメージをプリコンパイルできます。詳細については、「方法 : ASP.NET Web サイトをプリコンパイルする」を参照してください。

  • Internet Information Services 5.0 上で Web アプリケーションをアウトプロセスで実行する。   既定では、IIS 5.0 上の ASP.NET は、アウトプロセス ワーカー プロセスを使用して要求に対応します。この機能は、高速スループットを実現するように調整されています。ASP.NET をアウトプロセス ワーカー プロセスで実行することによって、その機能や利点が得られるため、実行用のサイトではこの方法をお勧めします。

  • 定期的にプロセスをリサイクルする。   安定性とパフォーマンスの両方を保つために、プロセスは定期的にリサイクルしてください。長時間が経過すると、メモリ リークやバグのあるリソースにより Web サーバーのスループットが低下します。プロセスをリサイクルすることで、メモリのこのような問題を一掃できます。ただし、定期的なリサイクルの必要性とリサイクルの頻度とのバランスを取る必要があります。ワーカー プロセスの停止、ページの再読み込み、およびリソースやデータの再取得による負荷が、リサイクルによる利点を上回る可能性があるためです。

    IIS 6.0 を使用する Windows Server 2003 で実行される ASP.NET Web アプリケーションでは、ASP.NET が IIS 6.0 プロセス モデルの設定を使用するため、プロセス モデルの設定を調整する必要はありません。

  • **必要に応じて、アプリケーションのワーカー プロセスごとのスレッド数を調整する。**ASP.NET の要求アーキテクチャは、要求を実行しているスレッド数と使用可能なリソースのバランスを取ろうとします。このアーキテクチャにより、CPU で処理できる同時実行要求だけを実行できます。この手法をスレッド ゲーティングと呼びます。ただし、スレッド ゲーティングが正しく機能しない場合もあります。ASP.NET Applications パフォーマンス オブジェクトに関連付けられた Pipeline Instance Count パフォーマンス カウンタを使用して、Windows パフォーマンス モニタでスレッド ゲーティングを監視できます。

    ASP.NET Web ページが外部リソースを呼び出すとき (たとえばデータベース アクセスを実行したり、XML Web サービス要求を実行したりするとき)、一般にページ要求は外部リソースが応答するまで停止し、CPU は他のスレッドを処理するために解放されます。他の要求が処理を待っている状態で、スレッド プールに空きスレッドがある場合は、待機中の要求の処理が開始されます。この結果、同時実行される要求数および ASP.NET ワーカー プロセスまたはアプリケーション プールの待機スレッド数が多くなるため、Web サーバーのスループットの妨げとなり、パフォーマンスに悪影響を及ぼします。

    この問題を緩和するには、Machine.config ファイルの processModel セクションで MaxWorkerThreads 属性および MaxIOThreads 属性を変更して、プロセス内のスレッド数の制限を手動で設定します。

    メモ :

    ワーカー スレッドは ASP.NET 要求を処理するためのものであり、IO スレッドはファイル、データベース、または XML Web サービスからのデータを処理するのに使用されます。

    プロセス モデルの属性に割り当てられたそれぞれの値は、プロセス内で CPU ごとに用意された各種スレッドの最大数です。2 プロセッサのコンピュータでは、最大数は設定値の 2 倍です。4 プロセッサのコンピュータでは、最大数は設定値の 4 倍です。既定値はプロセッサが 1 つまたは 2 つのコンピュータに適しており、プロセッサが 3 つ以上のコンピュータのプロセス内でスレッド数が 100 から 200 に達する場合は、パフォーマンスに対する利点よりも弊害が多くなります。プロセス内のスレッド数が多すぎると、余分なコンテキスト切り替えが発生し、オペレーティング システムは要求の処理よりもスレッドの管理に CPU サイクルを使用するため、サーバーの処理速度が低下します。適切なスレッド数は、アプリケーションのパフォーマンスをテストして決定することをお勧めします。

  • **外部リソースに大きく依存しているアプリケーションの場合は、マルチプロセッサ コンピュータ上で Web ガーデンを有効にすることを検討する。**ASP.NET プロセス モデルは、作業を複数のプロセス (CPU ごとに 1 つのプロセス、各プロセスのプロセッサ関連を CPU に設定) に配布することにより、マルチプロセッサ コンピュータのスケーラビリティを有効に使用できるようにします。この方法を Web ガーデンと呼びます。2 つの例を挙げると、アプリケーションが遅いデータベース サーバーを使用している場合や、外部依存関係を持つ COM オブジェクトを呼び出す場合には、アプリケーションに対して Web ガーデンを有効化することが効果的となる可能性があります。ただし、この機能を実行用 Web サイトに対して有効化することに決める前に、Web ガーデンを有効化した場合にアプリケーションがどの程度適切に動作するのかをテストする必要があります。

  • **デバッグ モードを無効にする。**製品版アプリケーションを配置する前またはパフォーマンス測定を実行する前には、必ずデバッグ モードを無効化します。デバッグ モードが有効な場合、アプリケーションのパフォーマンスが低下することがあります。デバッグ モードを設定する構文については、「ASP.NET 構成ファイルの編集」を参照してください。

  • **Web サーバー コンピュータおよび特定のアプリケーションの各構成ファイルを、必要に合わせて調整する。**既定では、ASP.NET 構成は、最大限の機能セットが有効に設定され、最も一般的なあらゆるシナリオに対応できるようになっています。使用する機能に応じて、既定の構成の一部の設定を変更し、アプリケーションのパフォーマンスを向上させることができます。考慮する必要のある構成の設定を次の一覧に示します。

    • **認証は、認証を必要とするアプリケーションに対してのみ有効にする。**既定では、ASP.NET アプリケーションの認証モードは Windows で、統合 NTLM ではありません。多くの場合、Machine.config ファイルでは認証を無効にし、認証を必要とするアプリケーションの Web.config ファイルでのみ認証を有効にすることをお勧めします。

    • **要求および応答のエンコーディング設定に合わせてアプリケーションを構成する。**ASP.NET の既定のエンコーディングは UTF-8 です。アプリケーションで ASCII 文字だけを使用する場合は、アプリケーションを ASCII に合わせて構成するとパフォーマンスが若干向上します。

    • **アプリケーションの AutoEventWireup を無効化することを検討する。**Machine.config ファイルで AutoEventWireup 属性を false に設定すると、ページは名前の一致に基づいたページ イベントのメソッドへのバインドを行いません (たとえば Page_Load など)。AutoEventWireup を無効にした場合は、イベントを自動的に実行するのではなく、開発者にイベント接続を任せることによって、ページのパフォーマンスが若干向上します。

      ページ イベントを処理する必要がある場合、次のいずれかの方法を使用します。1 つ目の方法は、基本クラスのメソッドをオーバーライドすることです。たとえば、Page_Load メソッドを使用するのではなくページ読み込みイベントを使用するように、Page オブジェクトの OnLoad メソッドをオーバーライドできます (確実にすべてのイベントを発生させられるように基本メソッドを呼び出してください)。2 つ目の方法は、Visual Basic では Handles キーワードを、C# ではデリゲート ワイヤアップを使用してイベントにバインドすることです。

    • **要求を処理するパイプラインから未使用のモジュールを削除する。**既定では、サーバー コンピュータの Machine.config ファイルの HttpModules ノード内のすべての機能は、アクティブのままになります。アプリケーションで使用する機能に応じて、不要なモジュールを要求パイプラインから削除して、パフォーマンスを多少向上させることができます。各モジュールとその機能を検討し、必要に応じてカスタマイズします。たとえば、アプリケーションでセッション状態や出力キャッシュを使用しない場合は、これらを HttpModules リストから削除することによって、意味のある他の処理を実行しないこれらの各モジュールを呼び出す必要がなくなります。

コーディングの技法

次のガイドラインでは、効率的なコードを記述するための推奨方法を示します。

  • **例外に依存するコードは記述しない。**例外によりパフォーマンスが著しく低下する可能性があるため、例外を使用して標準プログラム フローを制御することは避けてください。例外を発生させる条件をコードで検出できる場合は、例外そのものをキャッチして条件を処理するのではなく、コードを使用して検出します。例外をコードで検出する一般的な処理には、null に関するチェック、解析されると 1 つの数値になる String への値の代入、または数値演算の適用前の特定の値に関するチェックが含まれます。例外の原因となる可能性のあるコードと、条件についてテストするコードを次の例に示します。どちらも結果は同じになります。

    // This is not recommended.
    try {
       result = 100 / num;
    }
    catch (Exception e) {
      result = 0;
    }
    
    // This is preferred.
    if (num != 0)
       result = 100 / num;
    else
      result = 0;
    
    ' This is not recommended.
    Try
       result = 100 / num
    Catch (e As Exception)
      result = 0
    End Try
    
    ' This is preferred.
    If Not (num = 0)
       result = 100 / num
    Else
      result = 0
    End If
    
  • 多くの呼び出しを行う COM コンポーネントはマネージ コードで書き直す。.NET Framework には、従来の COM コンポーネントを容易に統合できる方法が用意されています。この方法を使うと、既存の COM コンポーネントを維持したまま .NET の機能を活用できるという利点があります。ただし、古いコンポーネントを維持することによるパフォーマンスへの影響が大きいために、コンポーネントをマネージ コードに移行した方がよい場合もあります。状況はそれぞれ異なるため、コンポーネントを移行する必要があるかどうかを判断するには、Web サイトについてパフォーマンス測定を実行することが最適な手段となります。頻繁に呼び出される COM コンポーネントのマネージ コードへの移植については、詳しく調べることをお勧めします。

    多くの場合、特に最初に Web アプリケーションを移行するときには、レガシ コンポーネントをマネージ コードに移行できません。このような場合、パフォーマンス上の最大の障害の 1 つはアンマネージ環境からマネージ環境へのデータのマーシャリングです。したがって、相互運用するときには、いずれか一方でできるだけ多くのタスクを実行し、一連の小さな呼び出しを行うよりも、1 つの呼び出しを行うようにします。たとえば、共通言語ランタイムのすべての文字列は Unicode であるため、マネージ コードへの呼び出しを行う前に、コンポーネント内のすべての文字列を Unicode に変換する必要があります。

    すべての COM オブジェクトやネイティブ リソースは、処理が終了したらすぐに解放します。これによって、他の要求で COM オブジェクトやネイティブ リソースを使用でき、後でガベージ コレクタを使ってこれらを解放することに関連するパフォーマンスの問題を最小限に抑えることができます。

  • **シングルスレッド アパートメント (STA: Single-Threaded Apartment) の COM コンポーネントは使用しない。**ASP.NET では、既定で、STA COM コンポーネントをページ内で実行できません。STA COM コンポーネントを実行するには、.aspx ファイル内の @ Page ディレクティブに ASPCompat=true 属性を含める必要があります。これによって、ページの実行に使用されるスレッド プールが STA スレッド プールに切り替えられ、HttpContext およびその他の組み込みオブジェクトは COM オブジェクトで利用できるようになります。STA COM コンポーネントを使用しないと、マルチスレッド アパートメント (MTA: Multithreaded Apartment) スレッドから STA スレッドへの呼び出しのマーシャリングが回避されるため、パフォーマンスの最適化にもつながります。

    STA COM コンポーネントを使用する必要がある場合は、実行中に多数の呼び出しを行うことは避け、各呼び出しでできるだけ多くの情報を送信するようにします。また、ページの構築時に STA COM コンポーネントを作成しないようにします。たとえば、次のコードでは、ページの構築時に SampleSTAComponent がインスタンス化されますが、このインスタンスは、ページを実行する STA スレッドではないスレッドから作成されます。この場合は、ページを構築するために MTA スレッドと STA スレッドの間でマーシャリングが必要になるため、パフォーマンスが低下する可能性があります。

    <%@ Page Language="VB" ASPCompat="true" %>
    <script runat=server>
    Dim myComp as new SampleSTAComponent()
    Public Sub Page_Load()
        myComp.Name = "Sample"
    End Sub
    </script>
    <html>
    <%
        Response.Write(Server.HtmlEncode(myComp.SayHello))
    %>
    </html>
    

    好ましい方法は、次の例に示すように、オブジェクトの作成を、コードが STA スレッドの下で実行されるときまで遅延させることです。

    <%@ Page Language="VB" ASPCompat="true" %>
    <script runat=server>
    Dim myComp
    Public Sub Page_Load()
        myComp = new SampleSTAComponent()
        myComp.Name = "Sample"
    End Sub
    </script>
    <html>
    <%
        Response.Write(Server.HtmlEncode(myComp.SayHello))
    %>
    </html>
    

    推奨する方法では、COM コンポーネントおよび外部リソースを必要時にのみ構築するか、または Page_Load メソッドで構築します。

    STA COM コンポーネントは、キャッシュやセッション状態などの共有リソースに格納しないでください。共有リソースに格納すると、STA COM コンポーネントを構築したスレッド以外のスレッドもコンポーネントにアクセスできるためです。STA スレッドが STA COM コンポーネントに対して呼び出しを行う場合、呼び出しを処理できるのはその STA COM コンポーネントを構築したスレッドだけであるため、作成元スレッドに呼び出しをマーシャリングする必要があります。このマーシャリングによって、パフォーマンスが大幅に低下し、スケーラビリティの問題が生じる可能性があります。このような場合は、COM コンポーネントを MTA COM コンポーネントの中に作成するか、コンポーネントをマネージ コードで書き直すことを検討します。

参照

概念

ASP.NET でのパフォーマンスの最適化

ASP.NET アプリケーションのパフォーマンスの監視

ASP.NET 用のパフォーマンス カウンタ

ASP.NET キャッシュ