---
title: Performance Profiler
description: "PetMatchPro ships a lightweight request profiler that writes coarse server-side timing lines to the PHP error log. Use it when a search page renders slowly and you need to see where the time goes - the API fetch, the card…"
url: "https://petmatchpro.com/docs/performance-profiler/"
updated: "2026-10-25"
category: Troubleshooting
---

# Performance Profiler

PetMatchPro ships a lightweight request profiler that writes coarse server-side timing lines to the PHP error log. Use it when a search page renders slowly and you need to see where the time goes - the API fetch, the card loop, a theme or third-party `the_content` filter running after the shortcode, or something else. It is a diagnostic aid, available on every license tier, that adds no markup and no measurable overhead when it is off.

The profiler is deliberately hard to turn on by accident: it logs nothing unless all three conditions below are met at once, so a visitor cannot trigger logging by guessing a query string.

## Enable It (wp-config.php)

Add this line to `wp-config.php`, above the `/* That's all, stop editing! */` comment:

```
define( 'PMP_PROFILE', true );
```

Defining the constant alone logs nothing. It is one of three required conditions:

1. `PMP_PROFILE` is defined as exactly `true`.
2. You are logged in as a user who can `manage_options` (an administrator).
3. The URL you load carries `?pmp_profile=1`.

Because an administrator is required, the profiling request always fetches live animal data - admins bypass the plugin's API cache - so the reported fetch time is a live partner-API call, not a cache read. The rendered HTML is byte-identical whether the profiler is active or not.

## Run It

While logged in as an administrator, open the search page you want to measure and add `?pmp_profile=1` to its URL (use `&pmp_profile=1` if the URL already has a query string):

```
https://example.org/adopt/dogs/?pmp_profile=1
```

Load the page normally. The profiler writes its lines as the request runs. Reload a few times to get a representative set - the first load after a code change or a cache clear is often slower than steady state.

## Where the Log Lands

The profiler writes with PHP's `error_log()`. Where that goes depends on your setup:

- If `WP_DEBUG_LOG` is `true`, lines land in `wp-content/debug.log`.
- Otherwise they go to your host's PHP error log.

Host-specific locations:

- **Kinsta:** MyKinsta > your site > Logs (choose the error log), or `logs/error.log` over SSH/SFTP.
- **LiteSpeed / InterServer and most cPanel hosts:** the PHP error log, usually surfaced in the host control panel's Logs or Errors section, or an `error_log` file in the site root.

Every line this profiler writes is prefixed `[PMP Profile]`, so you can isolate them:

```
grep "[PMP Profile]" wp-content/debug.log
```

## Reading the Output

Each line starts with the prefix, a six-character request id, and the page path, so lines from one page load group together and concurrent requests do not mix:

```
[PMP Profile] a1b2c3 /adopt/dogs/ ...
```

There are two kinds of line.

**Milestones** report the time in milliseconds since the request started, one per WordPress assembly step - for example `init`, `wp`, `template_redirect.start/.end`, `wp_head.start/.end`, `content.start`, `content.after11` (after shortcodes run), `content.end`, `pmp-search.start/.end`, `pmp-details.start/.end`, `wp_footer.start/.end`, and `shutdown.start`. One line lists every `the_content` callback as `priority:name`, and an extra `content.afterPrio.N` milestone is logged after each callback that runs at priority 11 or higher. A long gap between `content.after11` and a `content.afterPrio.N` line names the filter that is slow - this is exactly how the 8.25 slowdown (WordPress core rewriting the page once per image) was found.

**The search line** is one summary per `[pmp-search]` render, with coarse segments:

```
[PMP Profile] a1b2c3 /adopt/dogs/ search partner=AF method=lost_found cards=936 cache=bypass total=3180.4 | fetch=1850.2 | prepare=120.5 | cards=980.1 | after=60.3 | unaccounted=169.3
```

- **partner / method / cards** - which partner rendered, the method type, and how many cards were built.
- **cache** - `hit`, `miss`, or `bypass`. Because profiling requires an administrator, and admins bypass the API cache, this reads `bypass` and `fetch` is a live partner call. Non-admin visitors (who cannot profile) are the ones who get `hit`/`miss`.
- **fetch** - the API fetch (or cache read), including pagination and sort.
- **prepare** - sort/filter/field preparation before the card loop.
- **cards** - the template render (the per-card loop).
- **after** - everything after the loop (poster bar, size overrides, wrap-up).
- **unaccounted** - wall time inside the profiled span not captured by a named segment.

## Turn It Off

Remove the `define( 'PMP_PROFILE', true );` line from `wp-config.php`. The profiler stops immediately on the next request. There is no admin setting and no other switch to reset. On a busy site, remember that `debug.log` is not rotated automatically - see [Reading PMP Debug Logs](/docs/reading-debug-logs/#log-rotation).

## Related

- [Performance and Caching Best Practices](/docs/performance-caching-best-practices/) - the caching layers the fetch segment measures.
- [Reading PMP Debug Logs](/docs/reading-debug-logs/) - where logs land and how to grep them.
- [wp-config.php Configuration Constants](/docs/wp-config-constants/) - `PMP_PROFILE` and other operator toggles.

 Performance Profiler ultima modifica:  2026-10-24T13:49:55-04:00 da PetMatchPro
