Morning Girl

Web API, Windows, C#, .NET, Dynamics 365/CRM etc..

【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の半分ほどです。

正直思った以上の結果が出て、びっくり……。やっぱりベストプラクティスはちゃんと調べないとダメですね。

f:id:sugimomoto:20150409150858p:plain

以下、実際のコードです。

検証コード

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);
        }
    }
}

参考URL

blogs.msdn.com