Categories Performance Monitoring

Drupal 8: A View Into Performance

Templating in Drupal 8 relies on Twig, but monitoring Views performance is still an open question.

Drupal 8: A View Into Performance

This is part 4 in a 5-part series on performance in the upcoming Drupal 8. Check out part 3, on performance in Twig templating, here.

Views is one of the most installed Drupal modules with over two thirds of Drupal sites reporting that they have it installed. Soon, though, that number will go up: as of Drupal 8, Views is a core module! This effort started as a community effort and was announced as an official Drupal 8 initiative in a post by Dries explaining why this change is so exciting.

One of the reasons that Views is so popular is that it provides an ‘all-in-one’ answer without writing a single line of code. But there’s a reason that many programmers hate WYSIWYG editors: you see the result, but not the steps taken to produce it, and what you don’t know might come back to bite you. While a WYSIWYG editor will get you broken links or weird formatting, WYSIWYG data retrieval can have direct performance implications. A’straightforward’ View might fetch data in unexpected ways, and even ‘small’ changes like adding a node relationship can result in radically different queries. Worse, any scalability issues may only manifest when a View is run against production-like data. A View focusing on user content might start choking on a user who favorites hundreds of nodes instead of the five you tested with.

That’s not to say that there’s anything wrong with Views, as this problem is very common in ORMs in frameworks such as Django and Rails. In fact, because Views is more all-encompassing, it provides effective out-of-the-box solutions to some of these problems in the form of result, block, and page caching. However, Views aren’t cached by default, and even with Devel integration it provides minimal data on its performance.

Rather than using a profiler or debugger, it’s possible to monitor Views performance by integrating with its code. Structurally, Views can be broken down into a ‘build-execute-render’ pipeline. In Drupal 7, many hooks are available for interacting with this process and changing how Views are constructed. There have been many Views API changes over time, but this basic set of hooks can be used on Drupal 6 and 7 sites, and Drupal 8 continues that trend. The TraceView Drupal module implements these hooks to track time spent in Views:

The Views rendering step takes less time in Drupal 8 than in Drupal 7 because it is no longer responsible for generating HTML.

Examining identical Views in Drupal 7 and 8 reveals that less time is spent in the render step of the pipeline. The codebase has been extensively refactored, so comparing backtraces would be difficult, but I’ve already examined this discrepancy using TraceView in my last article about Twig, the new templating engine in Drupal 8. The Views pipeline still exists in Drupal 8, but the render step no longer generates the View’s HTML, meaning that the performance of a View has to be placed in the context of the rest of the request.

When I wrote about Twig, though, I didn’t cover more advanced use cases for Views. There are often multiple Views on a page, or sometimes even multiple displays from the same View. To compare how this works in Drupal 7 vs. Drupal 8, I made identical setups by creating nodes with Devel Generate, enabling the Archive and Recent Comments Views, and placing their blocks in a sidebar. Here are traces generated by visiting the full page version of the Archive:

A request to Drupal 7, with a segment of time spent in Views highlighted in white.

A request to the same configuration in Drupal 8, again with a portion of Views time highlighted in white. Drupal 8 performs much more initialization work before entering Views, and Twig rendering and cache setting afterwards.

I’ve already written about the overall structural changes in Drupal 8, but in this more complex example we can see that the Views flow actually has changed. In Drupal 7, TraceView detects a total of three Views layers – pretty much as expected on a full-page View with two Views blocks. In Drupal 8, on the other hand, the same configuration produces five Views layers! This sounds wrong, admittedly, but it turns out that this can be traced back to a rather curious-looking snippet from ViewsBlock.php:

  public function build() {
    if ($output = $this->view->executeDisplay($this->displayID)) {
      $output = $this->view->executeDisplay($this->displayID);?>

Thanks to this code, each Views-defined block gets two bites at the apple. The first pass builds, executes, and renders the View; it then hands the View off to Twig to generate HTML. But that output is augmented by a second pass, which only requires a re-render step in Views rather than building or executing. The View is then processed by Twig a second, final time to produce more HTML.

The same View creates two drupal_views layers, with Twig rendering calls after each.

Apart from rendering, though, the architecture of Views hasn’t seen as much change as other Drupal 8 ports. In some sense, the largest changes to Views performance will come from changes in how it’s used. Many outstanding Drupal 8 issues are related to reimplementing administrative pages in Views, and Views will also be the engine driving Drupal’s RESTful shift by providing an easy way to expose data. This means that Views is going to ‘eat’ many custom callbacks, like implementations requiring drupal_json_output. This is a great step forward for rapid Drupal development, but a side effect is that it will make Views even more of a Swiss army knife – and the more crucial portions of your site that Views drives, the more crucial it becomes to understand its performance characteristics.

James Meickle: James started as a hobbyist web developer, even though his academic background is in social psychology and political science. His favorite language is Python, his favorite editor is Sublime, and his favorite game is Dwarf Fortress.