【C#】【Dynamics CRM】並列処理の実行結果比較
今回はDynamics CRMで実際に並列処理結果を比べたらどうなるの? というのをやってみました。
実施方法は3種類。
・一つ目は単純にforを回して、レコードをCreateし続けるもの。
・二つ目は前回作成したParallel.ForによるCreate。スレッド数の制限は無し。
・三つ目はPrallel.Forでかつ、スレッドの上限を2つにし、ExecuteMultipleRequestを実行したものです。
それぞれ1万件づつ作成しています。
実行環境
Dynamics CRM Online 2015(7.0)
SDK 7.0
実施結果
まず結論から言えば、三つ目の【Parallel.For&ExecuteMultipleRequest】が一番はやく通常のCreate方法の3分の1ほどで実行できる結果となりました。
Parallel.Forを使用するだけでも、通常Createの半分ほどです。
正直思った以上の結果が出て、びっくり……。やっぱりベストプラクティスはちゃんと調べないとダメですね。
以下、実際のコードです。
検証コード
using System; using System.Threading.Tasks; using System.ServiceModel.Description; using System.Diagnostics; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Messages; using Microsoft.Xrm.Sdk.Client; namespace MyProject.ParallelCrm { class Program { static void Main(string[] args) { Uri serviceUri = new Uri("https://XXX.api.crm7.dynamics.com/XRMServices/2011/Organization.svc"); IServiceManagement<IOrganizationService> orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(serviceUri); ClientCredentials clientCredentials = new ClientCredentials(); clientCredentials.UserName.UserName = "XXX@XXX.onmicrosoft.com"; clientCredentials.UserName.Password = "XXX"; AuthenticationCredentials authCredentials = orgServiceManagement.Authenticate(new AuthenticationCredentials() { ClientCredentials = clientCredentials }); CreateNomal(orgServiceManagement,authCredentials); CreatePrallelFor(orgServiceManagement, authCredentials); CreatePrallelForMultiple(orgServiceManagement, authCredentials); Console.ReadKey(); } private static void CreateNomal(IServiceManagement<IOrganizationService> orgServiceManagement, AuthenticationCredentials authCredentials) { Stopwatch sw = new Stopwatch(); sw.Start(); using (OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(orgServiceManagement, authCredentials.SecurityTokenResponse)) { Entity account = new Entity("account"); for (int j = 0; j < 10000; j++) { account["name"] = string.Format("Parallel For : Count {0}", j); serviceProxy.Create(account); } } sw.Stop(); Console.WriteLine("End Create Nomal " + sw.Elapsed); } private static void CreatePrallelFor(IServiceManagement<IOrganizationService> orgServiceManagement, AuthenticationCredentials authCredentials) { Stopwatch sw = new Stopwatch(); sw.Start(); Parallel.For(0, 100, i => { using (OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(orgServiceManagement, authCredentials.SecurityTokenResponse)) { Entity account = new Entity("account"); for (int j = 0; j < 100; j++) { account["name"] = string.Format("Parallel For : Thread {0} : Count {1}", i, j); serviceProxy.Create(account); } } }); sw.Stop(); Console.WriteLine("End Create Parallel For " + sw.Elapsed); } public static void CreatePrallelForMultiple(IServiceManagement<IOrganizationService> orgServiceManagement, AuthenticationCredentials authCredentials) { Stopwatch sw = new Stopwatch(); sw.Start(); ParallelOptions option = new ParallelOptions() { MaxDegreeOfParallelism = 2 }; Parallel.For(0, 10, option, i => { using (OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(orgServiceManagement, authCredentials.SecurityTokenResponse)) { Entity account = new Entity("account"); var request = new ExecuteMultipleRequest() { Settings = new ExecuteMultipleSettings() { ContinueOnError = false, ReturnResponses = true }, Requests = new OrganizationRequestCollection() }; for (int j = 0; j < 1000; j++) { account["name"] = string.Format("Parallel For : Thread {0} : Count {1}", i, j); request.Requests.Add(new CreateRequest { Target = account }); } ExecuteMultipleResponse responseWithResults = (ExecuteMultipleResponse)serviceProxy.Execute(request); } }); sw.Stop(); Console.WriteLine("End Create Prallel For Multiple " + sw.Elapsed); } } }