Hi

we have a site with loads of entities and > 43.000 entities are loaded by entity_load() in og_menu_node_prepare().

Yes this is a very large number but we can't get around. So I try to figure why the entities are loaded at all and if we really need to do this.

The exact line is 642

        // Using the handler allows us to get user options from OG without
        // running through all the user's groups.
        $ids = entityreference_get_selection_handler($field, $instance)->getReferencableEntities();

I can't figure why you load all possible targets here as I don't know your module very well. But with this it will simply not scale. And I believe this is not a problem in configuration.

It seems that you only use the id of the entity so maybe this can be done by some EFQ and not by getReferencableEntities() as this function loads the full entity?

Can we please chat in IRC or do a hangout what we could to here to set some limits?

Comments

rv0’s picture

Actually, this is the exact method that organic groups is doing it.. I think it gets called multiple times (even in og_node_access)
The only way to know which groups can be selected is by asking the entity reference selection handler (as there can be completely custom implemented behavior there).
I dont know if there's a better way

> 43.000 is indeed a bit crazy, dont you have a way to limit the entities available for selection, or write a custom selection handler?
If those 43000 entities come with the same number of menus, OG Menu's front end will crash too.

Kars-T’s picture

Title: og_menu dies in og_menu_node_prepare() if there are too many referencable entities » og_menu scalability

I believe you are referring to line 525 in og_node_access()?

if (entityreference_get_selection_handler($field, $instance)->getReferencableEntities()) {

In this case it is a wrong use of the entity reference API. The return values is not used at all and all entities would be loaded. I will add an issue to og that they use

\EntityReference_SelectionHandler_Generic::countReferencableEntities()

here and avoid the problem.

For og_menu there seem to be more problems with scalability. It seems you are only needing the entity ids here. And than you loop them in og_menu_get_group_menus(). That would be > 43.000 queries than. Not good ;)

We have to find a way to circumvent all this and that og_menu can scale and shine! :)

Frank Ralf’s picture

Title: og_menu scalability » og_menu dies in og_menu_node_prepare() if there are too many referencable entities

#1477868: OG Scalability says OG is capable of handling +10.000 groups, though.

tstoeckler’s picture

Title: og_menu scalability » og_menu dies in og_menu_node_prepare() if there are too many referencable entities

Right I looked at og_menu_get_group_menus() and that should be fixed as well, maybe in a separate issue, I don't know.

For this issue, I think we would need some upstream changes in OG, but in terms of actual code this should be very easy to do.
If you look into EntityReference_SelectionHandler_Generic::countReferencableEntities() it does:

  public function countReferencableEntities($match = NULL, $match_operator = 'CONTAINS') {
    $query = $this->buildEntityFieldQuery($match, $match_operator);
    return $query
      ->count()
      ->execute();
  }

So there could be a EntityReference_SelectionHandler_Generic::getReferencableEntityIds():

  public function getReferencableEntityIds($match = NULL, $match_operator = 'CONTAINS') {
    $query = $this->buildEntityFieldQuery($match, $match_operator);
    return $query->execute();
  }

I guess we should open an issue titled "Introduce a EntityReference_SelectionHandler_Generic::getReferencableEntityIds()" in OG?!

Edit: Copy-paste failure
Edit2: Again...

rv0’s picture

I guess we should open an issue titled "Introduce a EntityReference_SelectionHandler_Generic::getReferencableEntityIds()" in OG?!

Actually, this originates in entityreference module., not in OG

In any case, 43000 menus will make the front end crash for sure.. The menu handling would need to be ajaxified

Kars-T’s picture

@tstoeckler I believe the method is inside EntityReference and not og. So EntityReference should get the method to get the ids.

@rv0 Maybe paged lists or ajax yes. But imho this should be done in any case so lets see what we can do together :)

Kars-T’s picture

Title: og_menu dies in og_menu_node_prepare() if there are too many referencable entities » og_menu scalability

Resetting the a title of this issue to a more "meta" title so we can coordinate the scalability issues from this issue.

tstoeckler’s picture

Title: og_menu dies in og_menu_node_prepare() if there are too many referencable entities » og_menu scalability
tstoeckler’s picture

Found #2063149: og_menu_node_prepare() does unneccessary heavy-lifting in some cases

I still don't fundamentally grok, why og_menu_node_prepare() does what it does, but this at least avoids the heavy processing in some cases.

rv0’s picture

Just had hard time debugging an older 2.x site with 1000 menus and a 4 big main menus. node/add page load time was 100 seconds
Eventually I could fix it only because the site doesn't allow manual selection of group audience (prepopulated from url).
So instead of loading all menu trees, I adapted the code to only load it for the groups provided in url(new node) or group audience fields (existing node).

However, this further raises the question if we should replace the menu select with an ajaxified version that only loads what is needed

anthonys’s picture

Issue summary: View changes

I think the AJAX version is what the menuperformance module does. Perhaps integrating with that would be a good idea.

rv0’s picture

I've been looking into this "getReferencableEntities()" part. It causes an entity_load on all items indeed.
But... If I replace it by:

 $result = entityreference_get_selection_handler($field, $instance)->buildEntityFieldQuery()->execute();

to just get the id's, it results in an equal memory footprint but even slower page rendering time. This is because the entities get loaded individually anyway further down the road (e.g.: og_user_access => og_is_group), where those individual loads come from cache in the current codebase.

rv0’s picture

added note to project page:

Disable menu blocks will completely halt the definition of menu blocks for OG Menu menus. This can improve performance in several places and un-clutter the admin ui.

anthonys’s picture

Thanks - that looks useful

dalin’s picture

Since this appears to be a meta issue, you all might be interested in #2881709