0

I have a 'Node reference' field via the References 7.x-2.1 module which is pointing at a View which returns up to ~5000 results. I'm also exposing this field as a filter in a separate View. The issue that I'm having is that these ~5k results are taking up to 20s to render, despite only 10 rows being shown to the browser.

Judging by XHProf's results, I thought the best way to do this was to cache the rendered results of the referenced View. That brought the time for references_plugin_display::render down from 20s down to 10s, but that still seems like a long time. The References module doesn't seem to have documentation.

Is there a way to skip rendering 'Node reference' options, or to generally speed this process up? If the solution is to change modules, is there a migration path from D6 References fields to the new module in D7?

1 Answer 1

0

I wound up replacing references_plugin_style with a custom, bare-bones plugin style in my_references_plugin_style.inc:

/**
 * @file
 * Handler for my_references_plugin_style.
 */
class my_references_plugin_style extends references_plugin_style {
  function render() {
    if (!empty($this->options['grouping'])) {
      throw new Exception(t('References list (fast) does not support grouping.'));
    }

    $options = $this->display->handler->get_option('references_options');

    // Play nice with View UI 'preview' : if the view is not executed through
    // _*_reference_potential_references_views(), just display the HTML.
    if (empty($options)) {
      // "Render" rows quickly
      foreach ($this->view->result as &$row) {
        $row = $row->node_title;
      }

      $function = new ReflectionMethod('views_plugin_style', 'render');
      return $function->invoke($this);
    }

    // Foreach supposedly has better performance than array_map
    // @see http://stackoverflow.com/questions/18144782/performance-of-foreach-array-map-with-lambda-and-array-map-with-static-function
    $results = array();
    foreach ($this->view->result as $input) {
      $results[$input->nid] = array(
        'rendered' => $input->node_title,
        'group' => '',
        'title' => $input->node_title,
      );
    }

    return $results;
  }
}

Then registering it with:

/**
 * Implements hook_views_plugins().
 *
 * references.module's references_style plugin was way too slow (110s to render ~5k rows),
 * so fork that style plugin and strip most of the functionality away.
 */
function my_views_plugins() {
  $plugins = array(
    'style' => array(
      'my_references_style' => array(
        'title' => t('References list (fast)'),
        'help' => 'Returns results as a PHP array of names + rendered rows. (Less bloat than "References list").',
        'handler' => 'my_references_plugin_style',
        'theme' => 'views_view_unformatted',
        'uses row plugin' => FALSE,
        'uses fields' => TRUE,
        'uses options' => FALSE,
        'uses grouping' => FALSE,
        'type' => 'references',
        'even empty' => TRUE,
      ),
    ),
  );
  return $plugins;
}

And including the .inc file in my module's .info file:

files[] = views/my_references_plugin_style.inc

Finally, I went to my Views' UI and updated the Formatter to the new "References list (fast)" format.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.