Is It Beneficial To Call ExecuteMultipleRequest From Within A Plugin?

若如初见. 提交于 2019-12-07 02:50:54

问题


I know the ExecuteMultipleRequest is a huge performance booster when performing batch updates from outside of CRM. What I don't know is if it is beneficial to call it from within a CRM plugin.

My current understanding is that the main performance gain from using the ExecuteMultipleRequest is in the actual SOAP messaging costs. So (for updating 5000 records) rather than sending 5000 separate Soap messages (each having to be serialized, authenticated, transferred, etc), that all have to be sent to the server, you can send just one message with 5000 records. But when called from a plugin, you're already on the server, so no SOAP calls will have to be made, and therefor there isn't a benefit to using it.

Is there some other potential benefit that I'm not seeing?


回答1:


So I did what I should have done before, and just created a plugin to test this. This is running on CRM 2013 on my local VM (Pre-Operation), so results can vary, but I'm seeing plain old Create taking about 290ms less per 100 entities

I first created this plug

public class ExecuteMultipleTester : PluginBase
{
    protected override void ExecuteInternal(Common.Plugin.LocalPluginContext pluginContext)
    {
        var watch = new Stopwatch();
        var service = pluginContext.OrganizationService;

        watch.Start();
        var request = new ExecuteMultipleRequest
        {
            Settings = new ExecuteMultipleSettings
            {
                ContinueOnError = false,
                ReturnResponses = false,
            },
            Requests = new OrganizationRequestCollection()
        };

        for (var i = 0; i < 100; i++)
        {
            request.Requests.Add(new CreateRequest
            {
                Target = new new_Year
                {
                    new_Year = i + "- B",
                    new_YearIntValue = i,
                }
            });
        }
        service.Execute(request);
        watch.Stop();

        var multipleCreate = watch.ElapsedMilliseconds;

        watch.Restart();
        for(var i = 0; i < 100; i++)
        {
            service.Create(new new_Year
            {
                new_Year = i + "- A",
                new_YearIntValue = i,
            });
        }
        watch.Stop();

        throw new InvalidPluginExecutionException(String.Format("ExecuteMultipleRequest Time was: {0}ms, Standard was: {1}ms", multipleCreate, watch.ElapsedMilliseconds));
    }
}

Registered the plugin and ran 10 tests. Here are the results (ASCII tables, oh yah!):

+------------------+---------------+-------+
| Execute Multiple | Sevice.Create | Diff  |
+------------------+---------------+-------+
| 777              | 408           | 369   |
| 493              | 327           | 166   |
| 614              | 346           | 268   |
| 548              | 331           | 217   |
| 577              | 312           | 265   |
| 675              | 313           | 362   |
| 574              | 318           | 256   |
| 553              | 326           | 227   |
| 810              | 318           | 492   |
| 595              | 311           | 284   |
+------------------+---------------+-------+
|                    Average Diff: | 290.6 |
+------------------+---------------+-------+

So from these results, there is no need to execute an ExecuteMultipleRequest from within a plugin. You're already on the server, having to execute more code to perform the same operation.

Update 1 - 1000 Creates Test against a full environment

I ran this test again for the creation of a 1000 records, and in a full fledged environment with separate boxes for SQL, Services, and Web. Very similar results (only ran 5 tests since it was taking a lot longer)

+------------------+----------+--------+
| Execute Multiple | Standard |  Diff  |
+------------------+----------+--------+
|            18922 | 15057    | 3865   |
|            18668 | 14946    | 3722   |
|            18162 | 14773    | 3389   |
|            19059 | 14925    | 4134   |
|            18334 | 15306    | 3028   |
+------------------+----------+--------+
|                  | Average  | 3627.6 |
+------------------+----------+--------+

Interesting thing was the time was around 25 times longer for 10 times more records, but the differences was only 12 times more. ( Attempted to do updates rather than deletes, but I kept on getting timeout errors, even at just one for each... Must have been creating some sort of infinite loop, just not sure what... )

For a 1000 creates, its almost 4 seconds slower. I wouldn't use it in my plugins...




回答2:


Those type of results fall in line with what I've seen when running tests on an all in one box (i.e. CRM Server, SQL, ... all contained in one machine). When run against a more traditional deployment, I've see those results inverse. Also, the gap widens significantly as more messages are added to your request. Consider increasing your loop to process 300, 500, or 1000 (The default max for ExecuteMultipleRequest) records and run it against a deployment that has separated the CRM Front End, CRM Async, and SQL servers out onto different boxes.




回答3:


I know this is an old question / answer, but since I found it in my research, I thought I'd also chime in with some information I found on MSDN:

Throttling of concurrent calls – for Microsoft Dynamics 365 (online) there is a limit of 2 concurrent ExecuteMultipleRequest executions per organization. If that limit is exceeded, a Server Busy fault is thrown before the first request is ever executed. For an on-premises deployment, throttling is not enabled by default.

https://msdn.microsoft.com/en-au/library/jj863631.aspx#limitations

Based on this, I would recommend never using ExecuteMultipleRequest in any circumstance except for initial data load scenarios



来源:https://stackoverflow.com/questions/28414718/is-it-beneficial-to-call-executemultiplerequest-from-within-a-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!