Drupal CMS 1.0 was just released and it promises a better out of the box experience for smaller Drupal sites and new Drupal users. We wanted to see how Drupal CMS performance compares to WordPress, since their out of the box features should be more comparable than between WordPress and Drupal Core.

At Tag1, we have been dedicating resources to performance testing of Drupal Core and Drupal CMS, and contributing significantly to Drupal core and contributed module performance for more than 15 years, so this also gives us an idea of how successful that has been in driving improvements.

Performance comparisons of CMSs are often not reliable or reproducible, for example running 15,000 requests against the front page of a site with Apache Bench does not tell you how that site will perform in production or even when visited with a browser - it’s load testing, not performance testing.

With the aim of making a test that is reproducible, is easy to set up, but which can also be extrapolated to real life situations, we minimized the set-up time, using ddev quick starts for the respective projects, while trying to look at multiple aspects of performance when comparing the two.

We’ve included the basic installation steps here so that people can try to reproduce our results.

The Set Up

For WordPress, we installed 6.7.1 via the Quick Start DDEV Guide .

For Drupal CMS, we downloaded the 1.0 release zip and ran the ddev quickstart launcher. We didn’t include any optional recipes, just the base recipe.

Drupal CMS includes an image in its default front page content, and WordPress does not. To ensure a more accurate comparison, we edited the default front page post and used an identical highlighted image - included here in case you want to reproduce our steps.

Otherwise, zero customization of configuration or content was done for the initial testing.

The Testing

After these steps, we logged out, in order to get a view of the site as a regular site visitor would see it, and viewed the front page of both sites. As you can see from the screenshots, they’re pretty similar. The individual article pages are also very similar, but wordpress enables comments for anonymous users out of the box by default, whereas Drupal doesn’t, so the front page seemed like a closer comparison.

Screenshots


Front page - WordPress WordPress Front Page

Frontpage - Drupal CMS Drupal CMS Front Page

Front End Performance

To get a very quick idea about the front end performance of a site, we can look at Lighthouse.

Both Drupal and WordPress scored 100 on Lighthouse’s performance report. Drupal scores slightly higher for accessibility and SEO, but only by a couple of percentage points. Drupal and WordPress sites in production generally do not score this highly, because they have added more features and custom theming which may affect the score. Also certain lighthouse metrics depend on the network connection to the server and a local install is the best possible case for that. However, it would be very easy for either default install to get lower scores if they didn’t follow best practices.

WordPress Mobile

WordPress Mobile


Drupal Mobile

Drupal Mobile


WordPress Desktop

WordPress Desktop

Drupal Desktop

Drupal Desktop


However, a 100% score on Lighthouse doesn’t mean there’s nothing to do to improve performance and compatibility. If we look at the diagnostics report, there is a bit more detail:

Diagnostic Report for WordPress Desktop:

WordPress Desktop Diagnostics

Diagnostic Report for Drupal Desktop:

Drupal Desktop Diagnostics

Now things are starting to get a bit more interesting.

Responsive Images

Both WordPress and Drupal CMS deliver responsive and resized images out of the box, but there are subtle differences.

Even though we uploaded the same source image, Drupal serves a much smaller image to users. This is more pronounced on desktop, where WordPress serves the original image and Drupal serves a resized version, but it’s also visible to a lesser extent on mobile. There is a WordPress issue open to improve this.

WordPress mobile lighthouse diagnostics:

Drupal Desktop Diagnostics

Drupal CMS converts images to WebP out of the box, and WebP conversion has been included with Drupal core for several years. For WordPress, WebP conversion is available as a contributed plugin.

WordPress core does support AVIF, but because AVIF is not yet supported by most webserver configurations, it’s not enabled by default. Drupal core has an issue to add AVIF support which is still in progress.

Drupal CMS is also more aggressive with its responsive images configuration in terms of resizing: WordPress delivers a 768x768px image to Lighthouse’s default mobile viewport, whereas Drupal’s is 512x288px, and WordPress delivers the original, unresized image on desktop whereas Drupal’s is 1360x520px. Drupal core’s install profiles are also similarly aggressive in terms of responsive image resizing, so the results would be similar, although this will depend on individual site configuration in the real world.

Overall Page Weight

Now it’s time to leave Lighthouse and go to the network tab.

A hard refresh of the WordPress front page loads the following:

Document: 10.7kb
CSS: 2 files 3kb compressed (18.9kb uncompressed)
JavaScript: 2 files 14.8kb compressed (40.0kb uncompressed)
One Font: 53kb
One image: 243kb

For Drupal CMS:

Document: 3.7kb
CSS: 2 files - 13.8kb compressed, (72.3kb uncompressed)
JavaScript: 1 file 5kb compressed, (16.4kb uncompressed)
Two Fonts: five files, 110kb in total
One image: 5.8kb

Neither make any AJAX or other similar requests.

Overall, both are pretty lightweight out of the box. Once you depart from default themes into custom themes, start adding things like tracking scripts, media embeds, or carousels, CSS and JavaScript weight can go up pretty fast.

The notable difference between the two platforms is that Drupal loads more CSS out of the box, while WordPress loads more JavaScript out of the box. To reduce Drupal’s default CSS weight, we need to complete the componentization of its CSS libraries. We could also consider looking at using variable fonts in Olivero to see if that’s an overall improvement in the download size.

WordPress inlines various CSS into the HTML header, this is why its HTML page weight is four times that of Drupal’s and contributes to the lower sizes of the CSS files it serves. Drupal CMS does not yet support this, however you can inline critical CSS into the header with Drupal contributed modules, and there’s an issue to implement support for inlining critical CSS in Drupal core.

However, apart from the image size, the differences aren’t huge, certainly not to differentiate Drupal and WordPress as platforms, given the much wider variations between individual sites.

Back End Performance

A lot of performance comparisons focus purely on raw wall time comparisons, but even when using tools like apache bench, unless you’re profiling on a dedicated environment, other tasks can drastically impact the performance of the server under test - they are load tests, not performance tests.

Instead, we used ddev’s Xhprof support to get summary information for the page, this allows us to get four different metrics:

  1. Total time taken
  2. Total number of function calls
  3. Total memory usage
  4. Number of database queries executed

Xhprof was only consulted after hitting the page a couple of times, to ensure caches were warm.

None of these metrics by themselves is reliable as a sole indicator of performance, but the four together gives us different axes to compare against. Xhprof adds its own overhead when profiling, but while this affects timing and perhaps memory, it doesn’t impact the other metrics like raw function calls and database queries.

If you have a better idea for how to compare, let us know.

Drupal

Overall Summary:
Total Incl. Wall Time (microsec): | 29,296 microsecs
Total Incl. MemUse (bytes): | 5,258,784 bytes
Total Incl. PeakMemUse (bytes): | 7,589,520 bytes
Number of Function Calls: | 7,178
Database queries: 4

WordPress:

Overall Summary:
Total Incl. Wall Time (microsec): | 182,643 microsecs
Total Incl. MemUse (bytes): | 7,926,920 bytes
Total Incl. PeakMemUse (bytes): | 7,926,920 bytes
Number of Function Calls: | 142,595
Database queries: 31

At this point, someone unfamiliar with WordPress and Drupal might say ‘How can it possibly be that WordPress is about seven times as slow as Drupal?’. But an experienced Drupal developer will just say ‘the internal page cache’ and roll their eyes.

Drupal Core includes an internal page cache module, which behaves similarly to a reverse proxy or CDN for anonymous HTML pages, but written in PHP, and it reduces the resources required to serve pages to anonymous users to the absolute minimum with a warm cache. This means both minimal database and object cache queries, as well as only loading a few PHP classes. If you have Varnish or a CDN configured to cache HTML pages, then you don’t need the internal page cache. WordPress generally does not rely on PHP autoloading so the full PHP codebase is included on every request.

WordPress has full page caching plugins, but none are included out of the box so weren’t included in this comparison. The most well known, Jetpack Boost, requires a monthly subscription to Automattic.

Readers can decide for themselves whether this is a fair comparison, but in case some decide that it’s not a fair comparison, we ran the same tests without Drupal’s internal page cache.

drush pm-uninstall page_cache

Overall Summary:
Total Incl. Wall Time (microsec): | 115,849 microsecs
Total Incl. MemUse (bytes): | 11,499,400 bytes
Total Incl. PeakMemUse (bytes): |11,513,096 bytes
Number of Function Calls: | 34,711
Database queries: 27

The Drupal request still completes in less than 2/3rds the time and with ¼ the function calls of WordPress, although an equivalent number of database queries. This shows that it’s not only the page_cache that is resulting in good Drupal backend performance -- though it does show off how performant page_cache can be out of the box.

If not due to page_cache, then how is Drupal's performance still so much better than Wordpress in this case? In part, this is because Drupal’s caching is multi-layered. Behind the page_cache module, which can only optimize requests for anonymous users, there is the dynamic_page_cache module, which allows individual parts of the page (header, sidebars, footers, individual content cards etc.) to be render cached separately for any user. Even when browsing between different pages on a site, many page elements don’t need to be generated from scratch and can instead be pulled from the cache.

Just to see what happened, we then uninstalled the dynamic_page_cache module, and got the following results:

drush pm-uninstall dynamic_page_cache

Overall Summary:
Total Incl. Wall Time (microsec): | 241,052 microsecs
Total Incl. MemUse (bytes): | 14,120,344 bytes
Total Incl. PeakMemUse (bytes): |14,490,848 bytes
Number of Function Calls: | 84,166
Database queries: 110

As you can see, the wall time, memory usage, and database queries are all now higher than WordPress, although functional calls are still lower. This is close to the sort of performance you would get with a completely empty dynamic_page_cache, and it’s still comparable to WordPress. Very few Drupal sites would run in production without dynamic_page_cache enabled, so this is close to a worst case.

Frankly, these results are pretty surprising - we knew that Drupal does lots of caching, but we thought that WordPress would be inherently more lightweight, especially with the additional contributed modules that Drupal CMS includes on top of Drupal Core.

What Didn’t We Cover

There are a lot of situations that these tests don’t cover. We didn’t look at:

  • efficiency of JavaScript and CSS serving across multiple pages
  • optimizing the hosting environment - adding redis or memcache and their respective application cache backends, which significantly reduces database queries.
  • authenticated user performance, including editors and admins
  • transaction performance - posting content, comments, or using features like ecommerce
  • performance with large amounts of content in the database - tens or hundreds of thousands of posts.
  • localized and multilingual sites
  • cold start performance, with a completely empty cache, for example after a code deployment

If you’re interested in comparing these, we’d love to see people try to reproduce our results, try out different scenarios, and maybe compare against other open source CMSs.

In conclusion, both Drupal CMS and WordPress offer good out-of-the-box performance. However, Drupal has a slight edge on front end performance due to betterimage optimization out of the box, and a bigger edge on back end performance due to its very mature and multi-layered caching strategy and leaner bootstrap.

Note that Drupal CMS’s results would not have been this positive without active performance testing via Tag1’s Gander performance testing framework, see our recent write-up on the improvements made to Drupal CMS performance between it’s alpha1 and 1.0 releases.

Thanks to Google Developer Relations Engineer and WordPress core committer Adam Silverstein for reviewing this post prior to publication.


Image by NomeVisualizzato from Pixabay