이것은 모든 문맥 때문에 긴 질문처럼 보입니다. 이 소설에는 2 가지 질문이 있습니다. 이것을 읽고 도움을 주실 시간을내어 주셔서 감사합니다.DB 구현을위한 메모리 매핑 된 MappedByteBuffer 또는 Direct ByteBuffer?
상황
내가 32 비트 또는 64 비트 시스템의 크기에 TB 이상으로 몇 KB의 데이터 파일로 작업 지원할 수있는 확장 가능한 데이터 저장소 구현에 노력하고있다.
데이터 저장소는 Copy-on-Write 설계를 사용합니다. 항상 새 데이터 나 수정 된 데이터를 데이터 파일의 끝에 추가하고 기존 데이터에 대한 내부 편집을 절대로하지 마십시오.
시스템에서 하나 이상의 데이터베이스를 호스팅 할 수 있습니다. 각각은 디스크상의 파일로 표현됩니다.
구현의 세부 사항은 중요하지 않습니다. 유일한 중요한 세부 사항은 파일에 지속적으로 추가하고 KB에서 TB, TB에서 TB로 증가시키면서 동시에 클라이언트 요청에 응답하는 읽기 작업을 위해 파일을 무작위로 건너 뛰는 것입니다.
최초 생각 나는 내가 효율적으로 호스트 OS에과에서 데이터의 메모리 상태를 관리의 부담을 밀어 수 있도록 메모리 매핑 된 파일을 사용하고 싶었 알고 언뜻
내 코드.
내 모든 코드는 append-to-file 조작을 on-write로 직렬화하고 동시에 여러 독자가 요청에 응답하기 위해 파일을 탐색하도록해야합니다.
디자인
개별 데이터 파일이 MappedByteBuffer의 한계는 2GB를 초과 할 수 있기 때문에, 내 디자인이 쓰기 오프셋 소요 오프셋으로 변환하는 추상화 계층을 포함 할 것으로 기대 특정 2GB 세그먼트 내부.
지금까지 너무 좋아...
문제
내가 너무 신경하기 시작했다 (아래 제안) 다른 디자인으로가는 할 수있는 더 좋은 방법이 될 수 있다고 생각하는 곳입니다 이.
"메모리 맵핑 된"관련 질문은 여기에 있으므로, mmap 호출은 할당시 연속적인 메모리 실행을 원하는 것에 민감합니다. 예를 들어, 32 비트 호스트 OS에서 메모리 조각화 때문에 2GB 파일을 mmap하려고하면 내 매핑이 성공할 가능성이 적어지고 대신 128MB 매핑 시리즈를 사용하여 전체 에 파일.
을 내가 그 디자인을 생각할 때, 심지어 1천24메가바이트의 mmap에 크기를 사용하여 말을하는 DBMS 몇 거대한 데이터베이스를 호스트하는 모든 1TB 파일을 말할으로 표시, 지금 수천 메모리에서 메모리 매핑 지역의이 그리고 Windows 7에서 다중 GB 파일을 통해 몇백 개의 mmap을 만들려고 테스트 한 결과 예외가 발생하지 않았으며 너무 많은 할당을 시도 할 때마다 실제로 segfault에 대한 JVM을 얻었습니다. 내 Windows 7 컴퓨터에서 비디오를 잘라내어 이전에 보지 못했던 OS 오류 팝업으로 다시 초기화했습니다.
"큰 파일"또는 "이것은 인위적인 예제"를 처리하지 않을 것이라는 인수에 관계없이 이러한 부작용 유형으로 코드를 작성할 수 있다는 사실이 내 내부 알람을 켭니다. 하이 - 경고 및 대체 impl (아래) 고려했다.
내 생각에, 메모리 매핑 된 파일에 대한 나의 이해는 파일이 커질 때마다 매핑을 다시 만들어야한다는 것입니다. 따라서 디자인에 추가 전용 인이 파일의 경우에는 문자 그대로 지속적으로 매핑됩니다. 성장.
파일을 청크로 늘리고 (한 번에 8MB) 매핑을 8MB마다 다시 생성하여이 문제를 어느 정도 해결할 수 있습니다. 그러나 이러한 매핑을 계속해서 다시 만들어야 할 필요가 있습니다. 노골적인 unmap feature supported in Java.
질문 # 1 2
이 시점까지 내 결과를 모두 감안할 때, 나는 주로 솔루션 솔루션 무거운를 읽거나 읽기 전용위한 좋은 해결책으로 메모리 매핑 된 파일을 기각 있지만 것 끊임없이 맵핑을 재창조해야 할 필요성을 감안할 때 무거운
그러나 주변의 풍경을 둘러싼 MongoDB를 둘러싼 메모리 매핑 파일을 둘러보고 여기에 핵심 구성 요소가 누락 된 것 같은 느낌이 듭니다. (2GB 익스텐트와 같은 방식으로 할당됩니다. 시간, 그래서 그들은이 논리와 함께 다시 매핑 비용을 해결하고 순차적 실행을 디스크에 유지하는 것을 돕고 있다고 생각합니다.
이 시점에서 문제가 자바의 맵핑 작업이 부족하여 내 용도로 사용하는 데 훨씬 위험하고 부적절하거나 내 이해가 잘못되어 누군가 나를 북쪽으로 가리킬 수 있는지 여부는 알 수 없습니다.
대안 디자인
다음과 같이 내가 mmap에 대한 이해가 맞다면 갈 것 이상으로 제안 메모리 매핑 하나의 대안 설계는 다음과 같습니다
하는 것은 합리적인 구성 크기의 a direct ByteBuffer 정의 (2, 4, 8, 16, 32, 64, 128KB 대략적으로) 어떤 호스트 플랫폼과도 쉽게 호환 될 수 있으며 (DBMS 자체에 대해 걱정할 필요가 없으며 시나리오를 혼란스럽게 만들지 않음) 원래 파일 채널을 사용하여 specific-offset reads 1 개의 버퍼 용량 덩어리 (buffer-capacity-chunk)를 가지고 있으며, 메모리 매핑 된 파일들을 전혀 무시하고있다.
이제 내 코드는 "전체 레코드를로드하기에 파일에서 충분히 읽었습니까?"와 같은 것에 대해 걱정해야합니다.
또 다른 단점은 OS의 가상 메모리 로직을 사용하지 않아 자동으로 더 많은 "핫"데이터를 메모리에 보관할 수 있다는 것입니다. 대신 OS에서 사용하는 파일 캐시 로직이 여기에 도움이 될만큼 커야 만합니다.
질문 # 2
(2) 나는이 모든에 대한 이해의 확인을 받았으면했다.
예를 들어, 파일 캐시가 환상적일 수도 있습니다. 두 경우 모두 (메모리 맵핑 또는 직접 읽기) 호스트 OS는 가능한 한 많은 최신 데이터를 유지하고 대용량 파일의 성능 차이는 무시할 수 있습니다.
메모리 매핑 된 파일 (인접 메모리)에 대한 중요한 요구 사항에 대한 필자의 이해가 잘못되었으며 모든 것을 무시할 수 있습니다.
를 사용했다 (심지어 10 배 메인 메모리 크기 주위 데이터 크기가 아니라 그것을 성능을 발견, 그들을 게시하시기 바랍니다 대답으로. 많은 사람들이이 질문을 읽고 통찰력을 사용할 수 있습니다. http://bugs.sun.com/view_bug.do?bug_id=6893654와 같이 mmapping을 둘러싼 버그 ("JVM segfault 및 그래픽 드라이버 충돌이 더욱 악화 되더라도!")이 많이 있습니다. 우아한 기본 기능은 관리되는 세상에서 복잡하고 추악합니다. –
@AleksandrDubinsky 당신은 (우아함이 우아 해지는 것에 대해) 정확히 맞습니다. - 마지막 결과는 시스템에 심각한 불안정성을 초래하지 않으면 서 mmap'ed 파일을 빨리 만들 수 없다는 것입니다 (이 스레드에서 명확하게했는지는 모르겠지만 나는 블루 스크린 내 윈도우 dev에 기계를 관리). 이 세부 사항은 피터 (아래)가 크로니클에서 상당한 성공을 거두었음에도 불구하고 AsyncFileChannel을 사용하여 파일 I/O를 사용하고 mmap을 피하기를 원했습니다. –
@AleksandrDubinsky 일단 VM과 내 컴퓨터 모두 mmapped 파일의 "잘못된 사용"이있는 무릎에 가져 왔을 때, 나는 그 경로로가는 것으로 끝났습니다. 그것들은 우아하고 환상적인 성능을 제공하지만 AsyncFileChannel에서 더 많이 읽었을 때 동일한 성능 (OS가 FS 및 디스크 컨트롤러와 I/O 순서를 사용하여 요청을 최적화 할 수있게 해줍니다)에 가깝게 느껴질 수 있습니다. 정말로 mmap 경로를 내려가고 싶다면, Peter는 전문가입니다. –