Best Practices to Optimize Performance in Drupal 8
Drupal, a content management system has the capability to serve large data in different formats based on business need. A business requirement could be a data exchange between two web properties or sourcing a data or consuming data from external sources. Also, Drupal is gaining confidence in today’s market and also widely being used as SAAS. Now questions raised by big organizations before adopting Drupal is about its ability in terms of functionalities, features, compatibility, flexibility and most important performance.
Performance is a most crucial piece in any web/desktop application. It can truly turn down the market of any application. For example: A chariot can comfortably pull 3 men with two horses however if few more people board the same chariot, it will either not work or the speed will be reduced. This is simply because you are running a chariot with a wrong infrastructure and the same analogy holds true in the case of a web/desktop application. There’s no disclaimer with an application like it will perform with only a specific kind of infrastructure or it will serve the content to only specific concurrent users or about the page load time. And there are no benchmarks given on any of the competitive portals like WordPress , Joomla or other CMS.
The intent to write this blog is to help you think in a different direction, i.e. if a site is not performing well as expected then it is imperative to understand the underlying issue and find an appropriate solution to optimize the performance rather than blaming the capabilities of the CMS. I will provide few insights of Drupal 8. Drupal 8 is new, elegant and more promising as compared to its earlier versions 6/7. The process to improve performance can be almost similar in all the versions, but unless you have some in-depth understanding you will not be able to handle critical situations.
Outlined below are few key points to keep in mind for performance optimization.
1) “Avoid any manual configuration of standard settings as application core code changes over time.” Drupal community keeps a track of performance loose poles and detects Drupal application components and dependencies and optimize it in every new core updates.
Drupal 8 started with merging 100s of contributed modules in it. This gives a strong backend and flexibility to handle complex data structure. Merging these modules in core isn’t easy as these modules are ported from Drupal 7 to Drupal 8 and then are merged. Stability of these ported/merged module was hindering at an early age of Drupal 8 in 2016 but now it has become quite stable. To stablize these ported core modules in projects; the developers have modified codes which does not follow the Drupal/Symfony standard and can impact the performance.
2) “List valuable transactions for monitoring in order to optimize performance”. We should not get bog down to unnecessary smaller operations instead should focus on critical operations of the site or the area where user hits are atmost. Basically this requires understanding of client-side performance impact which correlates to browser and device performance to originating site performance metrics.
Drupal 8 deployment requires an adequate cache strategy which should minimize database interactions before we actually see the database load on the server. Areas below must be overlooked before originating performance metrics :
- Server Cache (Varnish / CloudFront) : Verify anonymous user pages cached. This can be verified by checking log or URL header i.e. URL header should not have no-cache in Cache-Control.
$ curl -I http://www.yoursite.com Accept-Ranges: bytes Age: 0 Cache-Control: must-revalidate, no-cache, private Content-language: en Content-Type: text/html; charset=UTF-8 Server: nginx Strict-Transport-Security: max-age=31536000 Vary: Accept-Encoding Via: 1.1 varnish X-AH-Environment: prod X-Cache: MISS X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-Generator: Drupal 8 (https://www.drupal.org) X-Request-ID: v-bdcbc8d4-d269-11e6-b0bd-0efda0c0bb84 X-UA-Compatible: IE=edge X-Varnish: 1350530508 Content-Length: 76311 Connection: keep-alive
- Page Cache (http://www.yoursite.com/admin/config/development/performance) : Ideally it should be 6 hours but it depends on busniess requirement.
- View / Block Cache : While creating a view we should set caching based on its behavior. View add/edit pages has (advance -> other -> caching) section which provides flexibility to set caching based on following :
- None : No cache required
- Tag Based : Cache view/block based on URL
- Time Based : Cache view/block based on following timing :
- Query results : The length of time raw query results should be cached.
- Rendered : The length of time rendered HTML output should be cached.
Best approach for View caching is a tag based caching.
- Custom Block Cache: While creating a custom block we can also define cache in return parameters like below :
return array( '#theme' => “new_theme”, '#var1' => $var1, '#var2' => $var2, '#cache' => ['contexts' => ['url.path'] ], );
Best approach for setting cache is based on contexts. You can find more cache contexts on https://www.drupal.org/docs/8/api/cache-api/cache-contexts page.
- You can also define time based caching by specify max-age.
return array( '#theme' => “new_theme”, '#var1' => $var1, '#var2' => $var2, '#cache' => ['max-age' => 360 ], // Set 0 for no-caching );
- Data structure/Query Caching : Data structure caching reduces significant amount of database interaction and serves data directly to front-end. Following tool will be helpful regarding the same:
Here I would like to advocate Redis which is being widely used right now. Following configuration in settings.php to enable Redis cache. (Must have Redis server and module installed)
# Use for all bins otherwise specified. $settings['cache']['default'] = 'cache.backend.redis'; # Use this to only use it for specific cache bins. $settings['cache']['bins']['render'] = 'cache.backend.redis';
3) “Keep track of errors and exceptions originated from PHP”. Enable database logging and keep watching any warnings, exceptions and notices. If we reduce these errors it will improve PHP execution time and hence give positive impact on overall site performance.
4) “Keep HTML skeleton as simple as possible”. Drupal provides its own basic themes to start with. While creating new theme usually front-end developers simply overrides the required templates such as home page layout or node page and for rest of the pages they override CSS. This approach is fine for rapid development but then it adds a lot of unwanted layers in the HTML. For example :
A particular field item will be rendered under 5-6 layers. Ideally we should remove view, block and some other unwanted layer so that HTML output should be as simple as required. Default Drupal theme also tried to use semantic tags for node (<article>) and tried to wrap all the item under the same tag. Here we need improvement as page should be divided in different sections. See the link http://www.w3schools.com/html/html5_semantic_elements.asp for better understanding of HTML5 tags.