Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRM-20621 : manage tags: the tag usage count is not accurate #10441

Merged
merged 3 commits into from
Jun 17, 2017

Conversation

monishdeb
Copy link
Member

@monishdeb monishdeb commented May 30, 2017

@lcdservices
Copy link
Contributor

looks good. count is accurate and query is compatible with mysql 5.7

@colemanw
Copy link
Member

@monishdeb can you please fix the failing test?

@colemanw
Copy link
Member

@civicrm-builder retest this please

@monishdeb monishdeb merged commit 8229b3b into civicrm:master Jun 17, 2017
@monishdeb monishdeb deleted the CRM-20621 branch June 17, 2017 10:59
@colemanw
Copy link
Member

colemanw commented Jun 2, 2018

@monishdeb and @lcdservices I know it's been a year since this was merged but I'm hitting a major performance issue with it on my sandbox. Clicking on a tagset with a few dozen tags in it takes 8 seconds to load, I can imagine it would take significantly longer on a live site with a few hundred tags in a set.

The major bottleneck appears to be the 'usages' => civicrm_api3('EntityTag', 'getcount'... for every item in the list. That's a lot of api calls! And commenting it out takes the load time form 8 seconds to < 1 second.

But reading the code, it's also now calling up $childTagIDs = CRM_Core_BAO_Tag::getChildTags(); which is building a potentially massive array in memory, only to discard most of it which is redundant with the query above.

'usages' => civicrm_api3('EntityTag', 'getcount', array(
'entity_table' => array('IN' => $usedFor),
'tag_id' => $dao->id,
)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking we should get rid of this and not send usage data with the main payload. We can switch to lazy-loading it when clicking on an individual tag in the UI.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, lazy loading is complicated because more than one tag can be selected at once. Is it really impossible to get this data from a join in the query?

ORDER BY name";

// fetch all child tags in Array('parent_tag' => array('child_tag_1', 'child_tag_2', ...)) format
$childTagIDs = CRM_Core_BAO_Tag::getChildTags();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this absolutely necessary? If we don't need the usage data can we re-add the LEFT JOIN civicrm_tag child ON child.parent_id = tag.id back to the query? That seems to be the only purpose of loading this massive array into memory.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Problem with the left join is that it doesn't look deep down the hierarchy to retrieve level-N child tags, reason why I need to introduce this new fn to fetch the tag tree via recursive search. However, we can avoid this lookup on each call by storing the $childTagIDs array in a Civi::static variable? And need to ensure that whenever a tag got deleted/moved in the tag tree this static variable got repopulated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function, by design, does not need to look deep within the hierarchy. It only needs to know whether the tag has children or not. 1 level deep is fine.

if (!empty($_REQUEST['is_unit_test'])) {
return $result;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could remove this hack by making the CRM_Admin_Page_AJAX::getTagTree() function a one-line wrapper and move the logic to a BAO function that would do the work and could be more elegantly unit-tested.

@lcdservices
Copy link
Contributor

@colemanw FWIW we're using this on NYSS where some sites have ~2000 tags, and we have not noticed a performance hit on that page. I'll do some more testing to confirm, but it's been in production with this change for quite some time without complaint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants