2012-07-28 4 views
11

는 정수의 다음과 같은 배열이 상상 : PHP와 만 배열 아기

array(1, 2, 1, 0, 0, 1, 2, 4, 3, 2, [...]); 

정수

100 만 개 항목까지 계속을; 단지 하드 코딩되지 않고 미리 생성되어 JSON 형식의 파일 (약 2MB 크기)로 저장됩니다. 이러한 정수의 순서는 중요합니다. 일관성이 있고 항상 동일한 인덱스에서 동일한 값을 가져야하므로 매번 임의로 생성 할 수 없습니다. "좋아"나는 json_decode 약 2를 구문 분석해야하기 때문에 아마 합리적인 생각, "-

이 파일이 나중에 PHP에서 다시 읽을 경우 그냥 배열을 얻을 수는 700에서 900ms로한다 (예를 들면 + json_decodefile_get_contents 사용) 백만 자, 캐쉬하자. " APC는 약 68MB의 엔트리를 캐시하는데, 보통은 zvals가 크다. 그러나 APC에서이 배열을 다시 검색하는 것은 내 눈에 아직도 너무 많이 좋은 600ms을 필요로합니다.

편집 : APC는 백만 개의 항목 배열이 길고 무거운 과정 인 콘텐츠를 저장하고 검색하기 위해 직렬화/비 직렬화를 수행합니다.

그래서 질문 : 나는 백만 항목의 배열에 상관없이 PHP에서 데이터 저장소 또는 방법을로드하려는 경우

  • 나는이 대기 시간을 기대해야 하는가? 지금까지 내가 이해 APC는 zval 자체를 저장, 그래서 이론적으로 APC에서 검색하는 것은 아마도 (더 구문 분석, 변환없이, 아니 디스크 액세스)

  • 이유에 대한 느린 APC입니다 얻을 수있는만큼 빨리해야한다 그래서 겉으로보기에 단순한 무엇인가?

  • PHP를 사용하여 100 만 개의 항목 배열을 메모리에로드하는 효율적인 방법이 있습니까? RAM 사용을 가정하면 문제가되지 않습니다.

  • 인덱스를 기준으로이 배열의 조각에만 액세스 할 수 있습니다 (예 : 인덱스 15에서 인덱스로 청크를로드하는 경우). 전체 배열을 메모리에 실제로 저장하지 마십시오 (예, 이것이 정상적인 방법이라고 생각합니다. 모든 것을 알고 싶었습니다.) 전체 배열을위한 가장 효율적인 데이터 저장소 시스템은 무엇이겠습니까? 분명히 RDBM이 아닙니다. 나는 redis를 생각하고 있지만, 나는 다른 아이디어를 듣게되어 기쁩니다.

+1

[SplFixedArray] (http://php.net/manual/en/class.splfixedarray.php)를 사용해 보셨나요? – Buddy

+0

@Buddy는별로 다르지 않지만 메모리를 적게 사용하지만 APC는 오래 걸립니다. – Mahn

+1

숫자가 작고 배열이 정적 인 경우 대신 단일 1Mb 문자열 객체를 사용할 수 없습니까? – 6502

답변

3

정수가 모두 0-15라고합시다. 그런 다음 바이트 당 2를 저장할 수 있습니다 :

<?php 
$data = ''; 
for ($i = 0; $i < 500000; ++$i) 
    $data .= chr(mt_rand(0, 255)); 

echo serialize($data); 

실행하려면 지금 php ints.php > ints.ser

당신이 부하에 15

-0에서 1,000,000 임의의 정수를 포함하는 500,000 바이트 문자열을 가진 파일이 있습니다

<?php 
$data = unserialize(file_get_contents('ints.ser')); 

function get_data_at($data, $i) 
{ 
    $data = ord($data[$i >> 1]); 

    return ($i & 1) ? $data & 0xf : $data >> 4; 
} 

for ($i = 0; $i < 1000; ++$i) 
    echo get_data_at($data, $i), "\n"; 

내 컴퓨터의 로딩 시간은 약 0.002 초입니다.

당연히 이것은 당신의 상황에 직접적으로 적용될 수는 없겠지만, PHP 코드가 100 만 개가 넘는 것보다 훨씬 빠릅니다. 솔직히 말해서, PHP에서 큰 배열을 갖는 것은 결코 적절한 해결책이 아닙니다.

나는 이것이 적절한 해결책이라고 말하는 것은 아니지만, 귀하의 매개 변수에 맞는 것이면 확실히 실행할 수 있습니다.

배열의 정수가 0-255 범위에있는 경우 패킹을 제거하고 데이터를 ord($data[$i])으로 액세스 할 수 있습니다. 이 경우 문자열은 1M 바이트가됩니다.

마지막으로 file_get_contents()의 문서에 따르면 php가 파일을 메모리 맵핑합니다.그렇다면, 가장 좋은 성능을 파일로 원시 바이트를 덤프 할 수 있으며, 사용이 싶습니다

$ints = file_get_contents('ints.raw'); 
echo ord($ints[25]); 

ints.raw 정확하게 백만 바이트 있다고 가정합니다.

+0

Matthew, 제 제안서의 수 표형 버전을 이용해 주셔서 감사합니다. 몇 가지 사항 : 예'f_g_s()'는 대부분의 경우 파일에 mmap을 사용하지만 (예 : NFS 마운트 파일의 경우는 제외) 내용을 로컬로 할당 된 문자열로 복사합니다. 예, 'ord ($ ints [NNN])'액세스는 가장 효율적인 opcode 시퀀스를 생성합니다. 2mS는 파일 내용이 VFAT에 캐시되어 있기 때문입니다. 프로덕션 서버에서는 그렇지 않을 수 있습니다. – TerryE

+0

이것은 기본적으로 내가 6502와 TerryE가 제안했을 때 상상 한 것이지만 그럼에도 불구하고 쓰여진 것을 보니 정말 기쁩니다. 이 2ms는 아마도 파일이 @TerryE 언급처럼 캐시 되었기 때문에 발생하지만,이 파일을 APC에 캐시 할 수있는 좋은 기회가 있습니다. 나는 그것을 볼 것이다. – Mahn

+0

실제로, APC에서이를 저장하고 검색하는 작업은 간편하게 수행 할 수 있습니다. 성능과 메모리가 전체 배열을 메모리에 저장하는 것만 큼 좋을 수 있기 때문에이 대답을 받아 들일 것입니다. 내가 전체를 메모리에 저장해야하는지 여부는 아직 결정하지 않은 또 다른 질문이지만, 그 동안에는 더 나은 일을 할 것입니다. – Mahn

2

APC는 직렬화 된 데이터를 저장하므로 APC에서 다시로드 될 때 직렬화되지 않아야합니다. 그것이 당신의 간접비입니다.

로드하는 가장 효율적인 방법은 PHP로 파일에 쓰고()를 포함하는 것입니다. 그러나 백만 개의 요소가 포함 된 배열을 사용하면 어떤 수준의 효율성도 얻지 못할 것입니다 ... 엄청난 양의 메모리가 부족하여로드하는 데 시간이 걸립니다. 이것이 데이터베이스가 발명 된 이유입니다. 따라서 데이터베이스에 어떤 문제가 있습니까?

편집

당신이 항상 일치해야하고 있기 때문에

+1

그는 그것에 대해 들어 본 적이 없을 수도 있습니다. –

+0

예, 데이터베이스에 대해 들어 보지 못했습니다. 데이터베이스에 대한 정보가 없습니다. 데이터가 고정 된 것이기 때문에 APC와 같은 메모리에있는 단순한 작업이 더 나은 작업을 수행 할 것이라고 생각했습니다. APC가 데이터를 직렬화한다는 사실을 아는 것은 유감 스럽지만 나는 그렇지 않다는 생각을했습니다. – Mahn

+0

대부분의 캐시 (APC, memcache, redis 등)는 플랫폼 간 툴로 설계되어 있으므로 PHP 데이터 유형/zval 용으로 특별히 설계되지 않았기 때문에 데이터를 직렬화해야합니다. –

1

나는 무작위로 그것을마다 생성 할 수 없습니다, 직렬화/역 직렬화를 속도 igbinary 확장에서 살펴하려는 경우 같은 인덱스에서 같은 값을 갖는다.

의사 난수를 읽은 적이 있습니까? 이 문제를 다루는 시드라는 작은 것이 있습니다.

옵션 및 클레임을 벤치 마크하십시오. file_get_contents 대 json_decode를 타임 아웃 했습니까? 스토리지와 액세스 비용 사이에는 트레이드 오프가 필요합니다. 예 : 숫자가 0..9 (또는 0..255)이면 2Mb 문자열에 저장하고 이에 대한 액세스 함수를 사용하는 것이 더 쉽습니다. 2Mb는 FS 또는 APC에서 더 빨리로드됩니다.

+0

그래, 고정 된 씨앗을 기반으로 동일한 정수 목록을 알고리즘 적으로 생성하는 것은 내가 생각하고있는 옵션 중 하나이며, 아마도 가장 우아 할 수도 있습니다. 난 의사 난수를 조사해 그것이 내가 필요한 것에 적합 할 수 있는지 알아볼 것이다. – Mahn

1

Mark가 말했듯이, 데이터베이스가 생성되어 사용자의 일반적인 사용 패턴을 기반으로 데이터를 효과적으로 검색하고 조작 할 수 있지만 필요하지는 않을 수 있습니다. 또한 배열을 사용하여 자체 검색을 구현하는 것보다 빠를 수도 있습니다. 저는 우리가 배열에 접근 할 때마다 직렬화되기 전 2-300MB에 가까운 데이터가 직렬화되고 직렬화되지 않는다고 생각합니다.

속도를 높이려면 배열의 각 요소를 개별적으로 할당하십시오. 직렬화에 소요되는 시간 동안 함수 호출 오버 헤드를 교환 할 수 있습니다. 또한 자신의 확장 기능으로 이것을 확장하여 데이터 세트를 작은 검색 인터페이스로 래핑 할 수 있습니다.

내 상태가 포함되어 있기 때문에 zval을 직접 저장할 수없는 이유는 짐작할 수 있습니다. 단순히 변수 기호 표를 이전 표로 가리킬 수 없습니다.

관련 문제