Using profiling tools to identify slow modulesfor Drupal 11 , 10 , 9 , and 8

Last updated :  

Every technique in this section so far — removing unused modules, tightening hooks, lazy services — is a fix for a specific, known problem. This lesson is about finding those problems in the first place, rather than guessing. Profiling tells you exactly which module, which function call, is actually consuming your request's time, instead of optimizing based on intuition about what "feels" slow.

What you'll learn in this lesson

  • The difference between profiling and just watching total page load time
  • How to install and use the Devel module's Webprofiler for real request-level data
  • What to actually look for in a profile once you have one

Why "it feels slow" isn't enough

A page taking 800ms tells you nothing about where those 800ms went — 600ms of it could be one runaway query, or 50ms each spread across a dozen modules' hooks, or a single expensive service construction. Guessing which technique from this whole tutorial to apply, without knowing which one, wastes real effort optimizing something that was never actually the bottleneck.

Devel's Webprofiler

composer require drupal/devel
drush en devel devel_webprofiler -y

Once enabled, Webprofiler attaches a toolbar to every page showing real, per-request breakdowns: total execution time, database query count and individual query time, memory usage, and — critically for this section — which modules' hook implementations ran and how long each took.

Never leave profiling tools enabled on production. Webprofiler (and Devel generally) adds real per-request overhead of its own to collect all that data, and can expose internal application details in its toolbar. Use it on a staging environment or local copy under realistic data volume and traffic patterns, then uninstall it before deploying — profiling tools measuring themselves skews the very numbers you're trying to read.

What to actually look for

  • Query count spikes: dozens of near-identical queries usually means an N+1 problem — loading related data one row at a time inside a loop instead of batching it, exactly the mistake the Entity and Field Optimization section covered.
  • One dominant hook: if a single module's hook implementation accounts for a disproportionate share of total time, that's your highest-value optimization target — not the ten modules each taking 2ms.
  • Memory spikes correlating with specific requests: often points at a bulk operation or large dataset being loaded fully into memory rather than processed incrementally.

Quick check: Webprofiler shows 40 nearly-identical database queries on one page load, each individually fast. Is the fix likely a faster database server, or something else? If you said something else — specifically, batching those 40 queries into one loadMultiple() call, an N+1 pattern from the Entity and Field Optimization section — you've correctly diagnosed the actual problem instead of throwing hardware at a code-level issue.

Key takeaways

  • Profile before optimizing — "it feels slow" doesn't tell you which of this tutorial's many techniques actually applies.
  • Devel's Webprofiler gives real per-request data: query count/time, memory, and per-hook timing.
  • Never leave profiling tools enabled on production — they add overhead and can expose internal details.
  • Many near-identical queries usually mean an N+1 problem to batch, not a database that needs upgrading.

Coming up next

You've now got the tools to find exactly which module is costing you time. Next, we apply that same profiling discipline specifically to image handling — one of the most common real-world performance bottlenecks on a typical Drupal site.