Need an array-like structure in PHP with minimal memory usage

后端 未结 8 2205
星月不相逢
星月不相逢 2020-12-23 02:02

In my PHP script I need to create an array of >600k integers. Unfortunately my webservers memory_limit is set to 32M so when initializing the array the script a

8条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-23 02:55

    I took the answer by @deceze and wrapped it in a class that can handle 32-bit integers. It is append-only, but you can still use it as a simple, memory-optimized PHP Array, Queue, or Heap. AppendItem and ItemAt are both O(1), and it has no memory overhead. I added currentPosition/currentSize to avoid unnecessary fseek function calls. If you need to cap memory usage and switch to a temporary file automatically, use php://temp instead.

    class MemoryOptimizedArray
    {
        private $_storage;
        private $_currentPosition;
        private $_currentSize;
        const BYTES_PER_ENTRY = 4;
        function __construct()
        {
            $this->_storage = fopen('php://memory', 'rw+');
            $this->_currentPosition = 0;
            $this->_currentSize = 0;
        }
        function __destruct()
        {
            fclose($this->_storage);
        }
        function AppendItem($value)
        {
            if($this->_currentPosition != $this->_currentSize)
            {
                fseek($this->_storage, SEEK_END);
            }
            fwrite($this->_storage, pack('l', $value));
            $this->_currentSize += self::BYTES_PER_ENTRY;
            $this->_currentPosition = $this->_currentSize;
        }
        function ItemAt($index)
        {
            $itemPosition = $index * self::BYTES_PER_ENTRY;
            if($this->_currentPosition != $itemPosition)
            {
                fseek($this->_storage, $itemPosition);
            }
            $binaryData = fread($this->_storage, self::BYTES_PER_ENTRY);
            $this->_currentPosition = $itemPosition + self::BYTES_PER_ENTRY;
            $unpackedElements = unpack('l', $binaryData);
            return $unpackedElements[1];
        }
    }
    
    $arr = new MemoryOptimizedArray();
    for($i = 0; $i < 3; $i++)
    {
        $v = rand(-2000000000,2000000000);
        $arr->AddToEnd($v);
        print("added $v\n");
    }
    for($i = 0; $i < 3; $i++)
    {
        print($arr->ItemAt($i)."\n");
    }
    for($i = 2; $i >=0; $i--)
    {
        print($arr->ItemAt($i)."\n");
    }
    

提交回复
热议问题