How to Pre-Allocate Memory with PHP

Sharing is caring!

Does your code have enough memory to handle most/all errors?

We have some code that catches when the sites crash with ‘Allowed memory size exhausted‘ error in PHP.

It turned out that when a code in a plugin/theme has an infinite loop or tries to consume too much memory it exhausts it all.
This turned out to be problematic because there wasn’t enough memory for our code to show a user friendly error message and not just a blank screen or 500 Internal Server Error.

In the discussion linked at the end of this post there’s an interesting discussion how to safely handle and display the errors. Somebody came up with an interesting approach. They pre-allocated certain memory in php. Then in the function/method that handles the error they free it up so it the function can have enough memory to complete its task.

In our size we’re testing with 1MB buffer. If there’s a need we’ll increase it.

You can use this code to preallocate memory in php.

You need to instantiate the object and it will allocate the buffer.

How to allocate memory

This calls the constructor which automatically creates the memory buffer only the first time the class is instantiated.

WPSandbox_Memory_Allocator()::getInstance();

How to check php memory usage

WPSandbox_Memory_Allocator()::getInstance()->getMemory();

How to free memory

WPSandbox_Memory_Allocator()::getInstance()->freeMemory();
/**
 * We may need some memory to be allocated for some operations such as displaying errors.
* @see https://wpsandbox.net/980
*/
class WPSandbox_Memory_Allocator {
    private $memory = null;
    private $reserved_memory_size = 1024 * 1024;
    private static $instance = null;

    private function __construct()
    {
        $this->allocateMemory();
    }

    public function getMemory() {
        $used_mem = ((int) (memory_get_usage() / 1024)) . 'KB';
        return $used_mem;
    }

    /**
     * @return static
     */
    public static function getInstance() {

        if (empty(self::$instance)) {
            self::$instance = new static();
        }

        return self::$instance;
    }

    public function allocateMemory()
    {
        $this->memory = str_repeat(chr(0), $this->reserved_memory_size);
    }

    public function allocateMemoryPack()
    {
        $this->memory = pack('C1024*1024', ...array_fill(0, $this->reserved_memory_size, 0));
    }

    public function freeMemory()
    {
        $this->memory = null; // this seems to make php free it quicker than unsetting it.
        unset($this->memory);
        self::$instance = null; // can't unset a static var
    }

    public function __destruct()
    {
        $this->freeMemory();
    }
}

References

https://stackoverflow.com/questions/8440439/safely-catch-a-allowed-memory-size-exhausted-error-in-php

Sharing is caring!

Leave a Comment

Your email address will not be published. Required fields are marked *