Skip to content

Instantly share code, notes, and snippets.

@thebrainroom
Last active January 22, 2026 15:38
Show Gist options
  • Select an option

  • Save thebrainroom/f10eb6df9f9d6a89fa011be979ae2dc0 to your computer and use it in GitHub Desktop.

Select an option

Save thebrainroom/f10eb6df9f9d6a89fa011be979ae2dc0 to your computer and use it in GitHub Desktop.

Here is the comprehensive performance analysis with the recommended code remediation.

SPX Performance Analysis & Remediation

Based on the profiling data, the application suffers from significant performance bottlenecks caused by synchronous initialization of heavy components on every page load.

1. Primary Bottleneck: Session Blocking (~270ms)

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).

Code Solution: Lazy Loading Sessions

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
}

2. Secondary Bottleneck: Expensive Initialization (~38ms)

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_gocardless method performs multiple database queries (via get_field) and instantiates the heavy GoCardlessPro\Client library unconditionally on every page load via the plugins_loaded hook.
  • Observation: This adds ~40ms of unnecessary processing to every request.

Code Solution: Lazy Initialization

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.

3. Summary of Gains

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment