When logging in with admin_menu active, I see a 100% Apache server load that delays log-in by 20 seconds. Everything else in Drupal works reasonably fast considering the circumstances, but this very annoying log-in delay for an administrator log-in really sticks out. I cannot image that developers intentionally wanted to annoy administrators this way and I feel therefore free to designate this as a bug.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ñull’s picture

By using XHProf I could determine that by activating admin_menu I see a rise of 5M function calls or some 230 times more. This might be caused by the great number of (group) menus this site has. A way to improve performance might be to reduce reliance on menu related function calls and in stead rely more on database queries.

sun’s picture

We recently fixed #1841884: cache_admin_menu table truncated 400+ times when clearing the cache, but that's part of RC4 already.

If you are able to distill what exactly gets called due to admin_menu during login, I'm more than happy to investigate further and work on a fix with you.

ñull’s picture

FileSize
12.63 KB

The only thing I can share (attached) at this point are the two reports of the profiler, one without and one with admin_menu. Unfortunately I cannot give you access to the site because this concerns an Intranet. In a couple of weeks I might have time to set up an anonymised test system that replicates the problem. Then you can click on links of each function in the list and get more detail.

ñull’s picture

In this intranet of a large decentralised NGO there are many groups that maintain their own group menu. In total including the global menus there are 162 menus!

I am not sure what menus get processed by admin_menu at log-in. I am just guessing here (no time to get into the details of the code). If it goes indistinctly through all the menus, then may be the solution to this problem is to exclude all og_menu group menus from processing.

 

ñull’s picture

Version: 7.x-3.0-rc4 » 7.x-3.x-dev
Status: Active » Needs review
FileSize
6.11 KB

With the following hack I reduce processing to only system menus (added condition module=system to the queries). Attached the profiler report to see the difference. The answer is definitely in finding smarter queries.

function admin_menu_tree_dynamic(array $expand_map) {
  $p_columns = array();
  for ($i = 1; $i <= MENU_MAX_DEPTH; $i++) {
    $p_columns[] = 'p' . $i;
  }

  // Fetch p* columns for all router paths to expand.
  $router_paths = array_keys($expand_map);
  $first_and= db_and();
  $first_and->condition('module','system')
     ->condition('router_path', $router_paths);
  $plids = db_select('menu_links', 'ml')
    ->fields('ml', $p_columns)
    ->condition($first_and)
    ->execute()
    ->fetchAll(PDO::FETCH_ASSOC);

  // Unlikely, but possible.
  if (empty($plids)) {
    return array();
  }

  // Use queried plid columns to query sub-trees for the router paths.
  $query = db_select('menu_links', 'ml');
  $query->join('menu_router', 'm', 'ml.router_path = m.path');
  $query
    ->fields('ml')
    ->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), drupal_schema_fields_sql('menu_links')));

  // The retrieved menu link trees have to be ordered by depth, so parents
  // always come before their children for the storage logic below.
  foreach ($p_columns as $column) {
    $query->orderBy($column, 'ASC');
  }

  $db_or = db_or();
  foreach ($plids as $path_plids) {
    $db_and = db_and();
    // plids with value 0 may be ignored.
    foreach (array_filter($path_plids) as $column => $plid) {
      $db_and->condition($column, $plid);
    }
    $db_or->condition($db_and);
  }
  $db_and = db_and();
  $db_and->condition('ml.module','system')
  ->condition($db_or);
  
  $query->condition($db_and);
  $result = $query
    ->execute()
    ->fetchAllAssoc('mlid', PDO::FETCH_ASSOC);

  // Store dynamic links grouped by parent path for later merging and assign
  // placeholder expansion arguments.
  $tree_dynamic = array();
  foreach ($result as $mlid => $link) {
    // If contained in $expand_map, then this is a (first) parent, and we need
    // to store by the defined 'parent' path for later merging, as well as
    // provide the expansion map arguments to apply to the dynamic tree.
    if (isset($expand_map[$link['path']])) {
      $parent_path = $expand_map[$link['path']]['parent'];
      $link['expand_map'] = $expand_map[$link['path']]['arguments'];
    }
    // Otherwise, just store this link keyed by its parent path; the expand_map
    // is automatically derived from parent paths.
    else {
      $parent_path = $result[$link['plid']]['path'];
    }

    $tree_dynamic[$parent_path][] = $link;
  }

  return $tree_dynamic;
}

ñull’s picture

Title: High server load at log-in » og_menus uselessly included / high server load at log-in
Status: Needs review » Needs work

I noticed that after applying my hack still a lot of processing time is wasted. I still see all the group menus in the admin_menu. In core Drupal these og_menus are not listed either when you look at admin/structure/menu so why should they be in the admin menu.

The idea of a group menu is that the group maintains it, not the site administrator. With a large number of group menus, like in my case, I need to scroll down at the very bottom to find the menu settings in admin_menu, far from being practical.

Still need to work on this, but that will have to wait until I have more time.

johnv’s picture

This problem is not only with og_menus, but with every menu that adds entities to a menu (like taxonomy_menu).
Try this test case:
- disable admin_menu,
- add a new node/group: the page is fast
- add a new node/group and add it to a menu : the page is slow
IMO, this is a special case of a more generic problem.
The root cause (low performance) is described here:
#1905144: High load time for admin_menu upon user login/menu refresh
#1978176: Build menu_tree without loading so many objects
If you do not want to show your groups in the initial admin_menu, you might want to work on:
#420816: On-demand loading of dynamic paths and local tasks #1

So, is this a duplicate?
Also, can you create a proper diff/patch? ATM it is difficult to see the modifications you made.

truls1502’s picture

Issue summary: View changes
Status: Needs work » Postponed (maintainer needs more info)
Issue tags: +postponed2w

I am sorry for no reply until now.

There are many issues regarding this module admin_menu which is a bit difficult for us to follow up since some of the issues might be already outdated, or is already fixed by the module or any other modules or itself core which means that the problem might no longer need to be fixed.

We can see that the issue has been created for a few years ago, I hope it is okay for you that I am postponing the issue, and give you around two weeks. If you still face the problem, could you tell us the step by step when until you get the error message or what is frustrated you, and a list of modules you are using related to admin_menu and a screenshot that might help us? So it makes us easier to reproduce your issue.

However, after two weeks with no feedback - we will close this issue. So in case, you noticed it after the issue is closed, do not hesitate to reopen it like and fill information which is mentioned above.

So before giving us a feedback, do you mind to test it again with our latest 7.x-3.x-dev?

Thank you for understanding! :)

truls1502’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)
Issue tags: -postponed2w

This issue has been automatically marked as closed because it has not had recent activity after the last post.

However, if you or someone is still facing the same issue as described to the issue, could you please to re-open the issue by changing the status of the issue, and add an explanation with more details which can help us to reproduce your situation.

Again, thank you for your contributions! :)