Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is It Beneficial To Call ExecuteMultipleRequest From Within A Plugin?

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?

like image 827
Daryl Avatar asked Feb 09 '15 16:02

Daryl


People also ask

What is the use of plugins in CRM?

A plug-in is custom business logic (code) that you can integrate with Dynamics 365 Customer Engagement (on-premises) to modify or augment the standard behavior of the platform. Another way to think about plug-ins is that they are handlers for events fired by Dynamics 365 Customer Engagement (on-premises).


1 Answers

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

like image 67
Daryl Avatar answered Sep 20 '22 11:09

Daryl