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?
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).
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.
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With