최소한의 메모리 사용으로 PHP에서 어레이와 같은 구조가 필요합니다.
는 >정수 합니다.내 PHP 스 600k 이 을 합 만 들 니도 내 웹 는 불하게내웹서는입니다.memory_limit
어레이를 할 때 가 중단되고 32M 으를 화있설어으초레므로기때중다표단니메시됩시되가지고가트스립크할정이로되어▁32m▁message▁is▁aborts▁script▁with다니.
치명적 오류:8행의 /home/wwww/myaccount/html/mem_test.php에서 허용된 메모리 크기 33554432바이트가 모두 사용됨(71바이트 할당 시도)
저는 PHP가 배열 값을 일반 정수로 저장하지 않고 일반 정수 값(제 64비트 시스템에서 8바이트)보다 훨씬 큰 z 값으로 저장한다는 사실을 알고 있습니다.각 어레이 항목이 사용하는 메모리 양을 추정하기 위해 작은 스크립트를 작성했는데, 알고 보니 128바이트였습니다. 128!!!어레이를 저장하려면 73M 이상이 필요합니다.도 웹 제 하에 있지 는 웹 서버를 늘릴 수 .memory_limit
.
제 질문은 PHP에서 메모리를 적게 사용하는 어레이와 같은 구조를 만들 수 있는 가능성이 있는지 여부입니다.이 구조가 연관성을 가질 필요는 없습니다(일반 인덱스 액세스로 충분).또한 동적 크기 조정이 필요하지 않습니다. 어레이의 크기를 정확히 알고 있습니다.또한 모든 요소는 동일한 유형입니다.오래된 C 어레이처럼 말입니다.
편집: 그래서 deceze의 솔루션은 32비트 정수로 즉시 작동합니다.그러나 64비트 시스템에 있더라도 pack()은 64비트 정수를 지원하지 않는 것 같습니다.어레이에서 64비트 정수를 사용하기 위해 비트 조작을 적용했습니다.다음 스니펫은 누군가에게 도움이 될 것입니다.
function push_back(&$storage, $value)
{
// split the 64-bit value into two 32-bit chunks, then pass these to pack().
$storage .= pack('ll', ($value>>32), $value);
}
function get(&$storage, $idx)
{
// read two 32-bit chunks from $storage and glue them back together.
return (current(unpack('l', substr($storage, $idx * 8, 4)))<<32 |
current(unpack('l', substr($storage, $idx * 8+4, 4))));
}
가장 효율적인 메모리는 모든 것을 이진 파일로 압축하여 문자열에 저장하고 수동 인덱싱을 사용하는 것입니다.
$storage = '';
$storage .= pack('l', 42);
// ...
// get 10th entry
$int = current(unpack('l', substr($storage, 9 * 4, 4)));
이는 "어레이" 초기화를 한 번에 수행할 수 있고 구조에서 읽기만 하는 경우에 실현 가능합니다.문자열에 많은 양을 추가해야 하는 경우 이는 매우 비효율적입니다.이 경우에도 리소스 핸들을 사용하여 수행할 수 있습니다.
$storage = fopen('php://memory', 'r+');
fwrite($storage, pack('l', 42));
...
이것은 매우 효율적입니다. 이와 계속 할 수 .fseek
.
PHP Judy Array는 표준 PHP Array 및 SplunkFixed Array보다 훨씬 적은 메모리를 사용합니다.
"일반 PHP 배열 데이터 구조를 사용하는 백만 개의 항목이 있는 배열은 200MB가 소요됩니다.SplunkFixedArray는 약 90MB를 사용합니다.Judy는 8개의 메그를 사용합니다.Judy는 일반적인 php 어레이 구현보다 약 두 배의 시간이 소요됩니다."
가능하면 객체를 사용할 수 있습니다.어레이보다 메모리를 적게 사용하는 경우가 많습니다.또한 SplunkFixedArray도 좋은 옵션입니다.
하지만 실제로 필요한 구현에 따라 다릅니다.배열을 반환하는 기능이 필요하고 PHP 5.5를 사용하고 있는 경우.생성기 수율을 사용하여 어레이를 다시 스트리밍할 수 있습니다.
SpFixed Array를 사용해 볼 수 있습니다. 더 빠르고 메모리를 적게 사용할 수 있습니다(의사 의견에 따르면 최대 30% 절감됩니다).여기와 여기를 테스트합니다.
끈을 사용하세요. 그게 제가 할 일입니다.고정 오프셋(16자리 또는 20자리가 되어야 하나요?)에 있는 문자열에 저장하고 필요한 것을 얻기 위해 기질을 사용합니다.고속 쓰기/읽기, 매우 간편하고 600,000개의 정수를 저장하는 데는 최대 1,200만 개의 데이터만 필요합니다.
base_interval - 더 컴팩트하지만 최소한의 노력으로 정수를 base-10 대신 base-36으로 변환합니다. 이 경우 14자리 숫자는 9개의 영숫자로 저장됩니다.당신은 64비트 인트를 2개 만들어야 할 것이지만, 저는 그것이 문제가 되지 않는다고 확신합니다.(변환을 통해 6자 버전이 제공되는 9자리 청크로 분할할 수 있습니다.)
pack()/()unpack - 이진 패킹은 조금 더 효율적인 동일한 것입니다.다른 방법이 없으면 사용하십시오. 숫자를 두 개의 32비트 조각에 맞게 나누십시오.
600K는 많은 요소입니다.만약 당신이 다른 방법을 선택할 수 있다면, 저는 개인적으로 그것을 위해 데이터베이스를 사용할 것입니다.그런 다음 표준 sql/nosql 구문을 사용하여 항목을 추출합니다.memcache 또는 redis는 garantiadata.com 과 같은 쉬운 호스트를 가지고 있는 경우에 사용할 수 있습니다.아마도 APC.
@deceze로 답을 받아 32비트 정수를 처리할 수 있는 클래스로 포장했습니다.추가 전용이지만 메모리에 최적화된 간단한 PHP 배열, 대기열 또는 힙으로 사용할 수 있습니다.AppendItem과 ItemAt는 모두 O(1)이며 메모리 오버헤드가 없습니다.불필요한 fsek 함수 호출을 피하기 위해 currentPosition/currentSize를 추가했습니다.메모리 사용량을 제한하고 임시 파일로 자동 전환해야 하는 경우 대신 php://temp를 사용합니다.
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");
}
정수를 생성하는 방법에 따라 배열을 통과하고 개별 값으로 작업을 수행한다고 가정하면 PHP의 생성기를 사용할 수 있습니다.
언급URL : https://stackoverflow.com/questions/21333474/need-an-array-like-structure-in-php-with-minimal-memory-usage
'it-source' 카테고리의 다른 글
git: URL을 http: URL로 변환하는 방법 (0) | 2023.08.14 |
---|---|
도커 컨테이너를 중지 및 제거하는 단일 명령 (0) | 2023.08.14 |
PowerShell - Write-Host로 쓴 줄 덮어쓰기 (0) | 2023.08.09 |
Symfony2 엔티티 모음 - 기존 엔티티와의 연결을 추가/제거하는 방법은 무엇입니까? (0) | 2023.08.09 |
Git Bash로 사용자 및 암호 구성 (0) | 2023.08.09 |