6

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?

Bvrce
  • 2,170
  • 2
  • 27
  • 45
Daryl
  • 18,592
  • 9
  • 78
  • 145
  • uhm, maybe using the ExecuteMultipleRequest in certain cases will be completed before the 2 minutes limit? – Guido Preite Feb 09 '15 at 16:56
  • @GuidoPreite, assuming you're updating 5000 records in a plugin (maybe not a great idea now that I think about it. I may change the question to be a workflow instead), would it be faster than 5000 individual updates? If so, why? – Daryl Feb 09 '15 at 17:37
  • workflows inside sandbox have the same 2 minutes limit. Regarding that ExecuteMultipleRequest is what Microsoft wrote on MSDN https://msdn.microsoft.com/en-us/library/jj863631.aspx `n general, ExecuteMultipleRequest behaves the same as if you executed each message request in the input request collection separately, except with better performance` – Guido Preite Feb 09 '15 at 18:00
  • 1
    @GuidoPreite Apparently it should be edited to except with better performance when being executed from the client. My tests show it is slower from within a plugin. – Daryl Feb 09 '15 at 20:10
  • See link in question for other possible fault side effects if used in a plugin. One fails, they all fail. – keerz Feb 10 '15 at 06:02

3 Answers3

9

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...

Daryl
  • 18,592
  • 9
  • 78
  • 145
  • Thanks for doing the experiment. I commented on an answer the other week stating using ExecuteMultiple in a plug-in was not necessary (http://stackoverflow.com/a/28246303/394978) and it has been hanging over my head that I hadn't actually proven what I said. Now the evidence is clear for all to read. – Nicknow Feb 11 '15 at 04:55
  • I'm curious if you get the same results with a more complex entity, for example 5 lookups, 3 optionset, a couple of datetime and a bit of salt :) – Guido Preite Feb 12 '15 at 14:11
  • @guidopreite I'm having trouble coming up with any plausible theory why a more complex operation would execute faster for one method vs the other. You're welcome to try yourself though! – Daryl Feb 12 '15 at 14:16
1

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

jasonscript
  • 6,039
  • 3
  • 28
  • 43
0

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.

  • Welcome to SO! :) You make a good point. I don't care as much about performance on my VM as I do in an actual environment so I think this demands more testing... – Daryl Feb 13 '15 at 13:55