Here is the comprehensive performance analysis with the recommended code remediation.
Based on the profiling data, the application suffers from significant performance bottlenecks caused by synchronous initialization of heavy components on every page load.
Impact: 53.62% of total load time.
The most critical issue is within BES_Portal_Session::__construct. This method is called early in the request lifecycle and immediately executes session_start().
- Location: session.php
- Cause: PHP's default file-based session handler locks the session file on the disk. When a user has multiple concurrent requests (e.g., AJAX calls, opening multiple tabs), requests effectively become serial, waiting for the previous one to release the lock.
- Observation: This adds a flat ~270ms penalty to Time to First Byte (TTFB).
Modify the class to only start the session when data is strictly required.
File: session.php
public function __construct()
{
// REMOVED: session_start();
// REMOVED: $this->_session =& $_SESSION;
}
/**
* Internal method to ensure session is started only when needed
*/
private function ensure_session_started()
{
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if ($this->_session === NULL) {
$this->_session =& $_SESSION;
if (!isset($this->_session[self::KEY]) || !is_array($this->_session[self::KEY])) {
$this->_session[self::KEY] = array();
}
}
}
public function get($name)
{
// ADDED: Lazy load check
$this->ensure_session_started();
if (empty($this->_session) || empty($this->_session[self::KEY]))
{
return NULL;
}
// ... rest of function
}
public function set($name, $value)
{
// ADDED: Lazy load check
$this->ensure_session_started();
$session =& $this->_session[self::KEY];
// ... rest of function
}Impact: 7.56% of total load time.
The BES_Portal_Gocardless class initializes its full API client immediately upon construction, even on pages that do not use payment functionality.
- Location: gocardless.php
- Cause: The
init_gocardlessmethod performs multiple database queries (viaget_field) and instantiates the heavyGoCardlessPro\Clientlibrary unconditionally on every page load via theplugins_loadedhook. - Observation: This adds ~40ms of unnecessary processing to every request.
Stop initializing the client in the constructor. Instead, check if it's ready before using it.
File: gocardless.php
public function __construct($portal_instance)
{
$this->portal_instance = $portal_instance;
// REMOVED: $this->init_gocardless();
}
/**
* Accessor method to get the client, initializing it only if it doesn't exist
*/
public function get_client() {
if (empty($this->_gocardless)) {
$this->init_gocardless();
}
return $this->_gocardless;
}Note: You will need to update other methods in this class to use $this->get_client() instead of accessing $this->_gocardless directly, or add a check to init_gocardless() at the start of public methods.
| Component | Issue | Fix | Est. Improvement |
|---|---|---|---|
BES_Portal_Session |
Synchronous session_start() locks requests. |
Move session_start() to get/set methods (Lazy Load). |
~270ms |
BES_Portal_Gocardless |
Connects to external API/DB on every load. | Remove init_gocardless() from __construct. |
~40ms |