みなさん、こんにちは。
以前こちらの記事で、Web サービスのベストプラクティスを紹介し、
その中で プロキシクラスを保持することでパフォーマンスが向上
するという説明をしました。
ただし、OrganizationServiceProxy はスレッドセーフではないため、
マルチスレッドアプリケーションを利用する場合、各スレッドごとに
固有のプロキシを生成する必要があります。
OrganizationServiceProxy を生成する場合は、認証および各種
メタデータのダウンロードが伴いますが、同一アプリケーションで
利用する場合、これらは重複情報であり、オーバーヘッドとなります。
そこで SDK 5.0.12 では認証およびメタデータのダウンロード部分を
外だしにすることで、 OrganizationServiceProxy 生成時のオーバー
ヘッドを最小限にする手法が提供されています。
概要
まず以下のコードでメタデータの取得を行います。
IServiceManagement<IOrganizationService> orgServiceManagement =
ServiceConfigurationFactory.CreateManagement<IOrganizationService>( new Uri(organizationUrl))
そして以下のコードで認証を行います。
AuthenticationCredentials authCredentials = orgServiceManagement.Authenticate(credentials)
最後にこれらの情報を利用してプロキシを生成します。
// 設置型の場合
OrganizationServiceProxy (orgServiceManagement, authCredentials.ClientCredentials)
// IFD、オンラインの場合
OrganizationServiceProxy (orgServiceManagement, authCredentials.SecurityTokenResponse)
検証1 (設置型 マルチコア)
開発者は論より証拠ということで、いつも通り検証をしてみます。
検証環境は Hyper-V 上の Windows Server 2008 R2 で、CPU を
論理コアで 4 つ割り当てています。
またアプリケーションの処理は以下の通りです。
1. Parallel.For で 20 スレッド作成し、各スレッド内で 100 件ずつ取引先企業を作成。
レコード 1 件作成ごとに、ベストプラクティスにそって OrganizationServiceProxy 生成。
2. Parallel.For で 20 スレッド作成し、各スレッド内で 100 件ずつ取引先企業を作成。
レコード 1 件作成ごとに、ヘルパーコードを利用して OrganizationServiceProxy 生成。
3. Parallel.For で 20 スレッド作成し、各スレッド内で 100 件ずつ取引先企業を作成。
レコード 1 件作成ごとに、従来の方法で OrganizationServiceProxy 生成。
4. 最初に OrganizationServiceProxy を 1 度だけ生成し、ループ処理で 2000 件の
取引先企業レコードを作成。
5. Parallel.For で 2000 スレッドを作成し、各スレッド内で 1 件ずつ取引先企業を
作成。各スレッドごとに、ベストプラクティスにそって OrganizationServiceProxy 生成。
したがって 4 以外は OrganizationServiceProxy を 2000 回生成しています。
結果は以下の通りです。
この結果より、従来の方法よりベストプラクティスのパフォーマンスが
良いこと、またヘルパーコードでもベストプラクティスを利用している
ことがわかります。また従来の方法でもマルチスレッドにすることにより、
同じプロキシインスタンスを再利用する場合と変わらない数値が
出ています。
検証 2 (設置型 シングルコア)
次に同一の Hyper-V に論理 CPU を 1 コアのみ付与して検証します。
再起動後、Internet Explorer より手動で 1 件取引先企業を作成した後、
検証を行いました。
シングルコアの場合、今回のような処理ではマルチスレッドのメリットが
出にくいようですが、1、2 ともに一度しか OrganizationServiceProxy を
生成しない場合と比較しても良好な結果を出しています。その一方で
本来の手法で OrganizationServiceProxy を生成し続けた場合、結果は
2 分 17 秒と、一度しか生成しないパターンの倍かかっています。
検証 3 オンライン環境
全く同じアプリケーションを、今度はオンライン環境に対して実行します。
OrganizationServiceProxy 生成時の引数で authCredentials.SecurityTokenResponse
を利用する点と、生成するレコード数を 100 件に減らして検証しました。
マルチスレッドの箇所は 10 スレッド作成、各スレッドで 10 レコード作成。
5 つ目の結果は 2000 パラレルとありますが、実際は 100 です。
ここでもマルチスレッドの効果が見て取れるものの、ヘルパークラスを
利用している場合に、パフォーマンスの低下が見られます。また以前の
方法で OrganizationServiceProxy を作成する場合のパフォーマンスの
悪さが見て取れます。
ヘルパーコードを利用した場合に、パフォーマンスが低下する理由は
OrganizationServiceProxy を生成する場合、オンライン環境に対して接続
すると、毎回 IServiceManagement の再作成をするためで、ヘルパーコードの
該当箇所を変更して、一度作成した後はキャッシュを利用するようにすると、
以下の結果を得ることができます。
‐ Dynamics CRM サポート 中村 憲一郎