CRM-21108 - Greatly improve performance of adding contacts #10906
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview
It currently takes 21 seconds to add 200 contacts using
CRM_Contact_BAO::create()
. #10905 shaves off 4 seconds from that; this PR shaves off another 10, resulting in a 2x to 3x speedup in creating contacts.Before
Creating 200 contacts takes ~17 seconds (after #10905 is applied), greeting processing takes 13.6 seconds:
After
Creating 200 contacts takes 6.5 seconds, greeting processing takes 3.0 seconds:
Technical Details
Greetings tokens are calculated by loading a contact's data into an array (via
DAO->find()
), replacing tokens with that data, then checking if there are any unreplaced tokens. If any tokens are unreplaced, Civi makes two (very expensive!) calls toCRM_Contact_BAO_Query
. Since non-contact tokens in greetings are rare, this should happen only rarely.Unfortunately, the greetings code doesn't account for the fact that fields that are NULL in the database won't appear in the object created by
DAO->find()
. Since the default addressee greeting has 5 tokens, you end up with a very slow greeting replacement unless your contacts have all of the following: prefix, suffix, first name, middle name, last name.Finally, there need not be two calls to
CRM_Contact_BAO_Query
; one is sufficient.By identifying and removing contact tokens whose values are null, we avoid the expensive calls. On the rare occasion such a call is needed, we still save ~6 seconds by calling the function once instead of twice.
Comments
You don't need a profiler to confirm this; you can download this file, rename to
contactprofiler.php
, save it in your civiroot, and run it withphp contactprofiler.php
.contactprofiler.php.txt