2008-10-10 3 views

답변

44

나는 이점이 실제로 파일을 읽는 전통적인 방법보다 필요한 데이터 복사량을 줄인다 고 생각합니다.

응용 프로그램에서 메모리 매핑 파일의 "적절한 위치에있는"데이터를 사용할 수 있으면 복사하지 않고 들어올 수 있습니다. 시스템 호출 (예 : Linux의 pread())을 사용하는 경우 일반적으로 커널이 자체 버퍼에서 사용자 공간으로 데이터를 복사하는 과정이 필요합니다. 이 여분의 복사는 시간이 걸릴뿐만 아니라 여분의 데이터 복사본에 액세스하여 CPU 캐시의 효율성을 떨어 뜨립니다.

실제로 물리적 인 I/O처럼 디스크에서 데이터를 읽어야하는 경우 OS에서 여전히 읽어야하며 페이지 호출은 시스템 호출보다 성능면에서 좋지 않습니다. , 그렇지 않은 경우 (즉, OS 캐시에 이미 있음) 이론적으로 성능이 훨씬 좋아야합니다.

단점은 메모리 매핑 파일에 비동기 인터페이스가 없다는 것입니다. 매핑되지 않은 페이지에 액세스하려고하면 페이지 폴트가 생성되어 스레드가 I/O를 기다립니다.


메모리 매핑 파일의 명백한 단점은 32 비트 OS에서 발생합니다. 주소 공간이 부족할 수 있습니다.

+2

좋은 **이 여분의 데이터 사본에 액세스하여 CPU 캐시의 효율성을 감소시킵니다. ** ". (** 강조 ** 광산). 커널의 여분의 버퍼 복사본이 어떻게 CPU의 캐시 효과를 방해하는지 설명해 주시겠습니까? –

+0

를 사용하여 매우 큰 파일을 처리하는 것보다 더 efficent을 할 수 있습니다 - 적어도 더 큰 mmap에 파일의 여러 32 비트 뷰를 매핑 할 수 있습니다 Windows의 경우 : – Geek

+2

@Geek는 두 배의 메모리에 액세스 = 두 배의 캐시가 낭비되었습니다 (대략적으로). – immibis

1
  • 쉽게 : 특히

    , 나는 중요한 순서대로 다음에 대한 걱정

    동시성이 문제가됩니다. 임의 액세스가 더 쉽습니다. 성능이 우수합니다. 사용 편의성. 좋지 않아. 휴대 성 - 너무 뜨겁지 않습니다.

    저는 오래 전에 썬 시스템에서 사용 해왔고 그 생각이 저의 것입니다.

  • 18

    메모리 매핑 된 파일을 사용하여 읽기/쓰기 액세스를 바꾸거나 동시 공유를 지원할 수 있습니다. 하나의 메커니즘에 이들을 사용하면 다른 것도 얻을 수 있습니다.

    파일에서 lseeking 및 쓰기 및 읽기보다는 메모리에 매핑하여 예상되는 위치에 간단하게 액세스 할 수 있습니다.

    이것은 매우 편리 할 수 ​​있으며 가상 메모리 인터페이스에 따라 성능을 향상시킬 수 있습니다. 성능 향상은 운영 체제가 다른 모든 프로그래밍 방식 메모리 액세스와 함께 이전의 "파일 I/O"를 관리하고 (이론적으로) 이미 지원을 위해 사용하고있는 페이징 알고리즘 등을 활용할 수 있기 때문에 발생할 수 있습니다 프로그램의 나머지 가상 메모리 그러나 기본 가상 메모리 시스템의 품질에 따라 다릅니다. 필자가 들었던 일화는 솔라리스와 * BSD 가상 메모리 시스템이 리눅스 VM 시스템보다 더 나은 성능 향상을 보일 것이라고 말합니다. 그러나이를 뒷받침 할 실증적 인 데이터는 없습니다. YMMV.

    동시성은 매핑 된 메모리를 통해 동일한 "파일"을 사용하는 여러 프로세스의 가능성을 고려할 때 그림과 함께 나타납니다. 읽기/쓰기 모델에서 두 프로세스가 파일의 동일한 영역에 기록하면 프로세스의 데이터 중 하나가 파일에 도착하여 다른 프로세스의 데이터를 덮어 쓰게됩니다. 당신은 하나 또는 다른 것을 얻을 것입니다 - 그러나 이상한 혼합은 아닙니다. 나는 이것이 어떤 표준에 의해 위임 된 행동인지 아닌지를 인정해야하지만, 당신이 많이 의지 할 수있는 무언가이다. (실제로는 후속 질문이 있습니다.)

    매핑 된 세계에서 대조적으로, 두 프로세스가 모두 "쓰기"라고 상상해보십시오. 그들은 "메모리 저장"을 수행함으로써 O/S 페이징으로 데이터를 디스크에 출력합니다. 그러나 그 동안 중복 된 쓰기가 발생할 것으로 예상 될 수 있습니다.

    다음은 예입니다. 두 개의 프로세스 모두 오프셋 1024에서 8 바이트를 쓰는 것으로 가정합니다. 프로세스 1은 '11111111'을 쓰고 프로세스 2는 '22222222'를 쓰고 있습니다. 그들이 파일 I/O를 사용한다면 O/S의 깊은 곳에서 상상할 수 있습니다. 1s로 가득 찬 버퍼와 2s로 가득 찬 버퍼가 있습니다. 둘 다 디스크의 같은 위치로 향하게됩니다. 그 중 하나가 먼저 도착하고 다른 하나는 도착할 것입니다. 이 경우 두 번째 것이 이깁니다. 그러나 메모리 매핑 된 파일 접근 방식을 사용하는 경우 프로세스 1은 4 바이트의 메모리 저장소로 이동하고 4 바이트의 다른 메모리 저장소가옵니다 (최대 메모리 저장소 크기는 아님).프로세스 2도 동일한 작업을 수행합니다. 프로세스가 실행하면 바탕으로, 다음 중 하나를 볼 것으로 예상 할 수 있습니다

    11111111 
    22222222 
    11112222 
    22221111 
    

    이에 대한 해결책은 명시 적으로 상호 배제 사용하는 것입니다 - 아마 어떤 경우에하는 것이 좋습니다. 당신은 일종의 O/S에 의존하여 일종의 I/O 파일 읽기/쓰기에서 "옳은 일"을 수행했습니다.

    분류 상호 배제 프리미티브는 뮤텍스이다. 메모리 매핑 파일의 경우, (예를 들어) pthread_mutex_init()를 사용하여 사용할 수있는 메모리 매핑 뮤텍스를 살펴 보시기 바랍니다.

    맵핑 된 파일을 사용할 때, 파일 자체의 데이터 (맵핑 된 파일에 저장된 링크 된 목록)에 포인터를 삽입하려는 유혹이 있습니다. 파일을 다른 시간에 다른 절대 주소 나 다른 프로세스에 매핑 할 수 있기 때문에이 작업을 원하지 않습니다. 대신 매핑 된 파일 내에서 오프셋을 사용하십시오.

    43

    사용자가 입력하는 동안 메모리 매핑 된 파일을 사용하여 '자동 완성'기능을 구현했습니다. 단일 인덱스 파일에 1 백만 개가 넘는 제품 부품 번호가 저장되어 있습니다. 파일에는 몇 가지 일반적인 헤더 정보가 있지만 파일의 대부분은 키 필드에 정렬 된 고정 크기 레코드의 거대한 배열입니다.

    런타임에 파일은 메모리 매핑되어 C- 스타일 struct 배열로 캐스트되고 사용자 유형으로 일치하는 부품 번호를 찾기 위해 바이너리 검색을 수행합니다. 파일의 일부 메모리 페이지 만 실제로 디스크에서 읽습니다. 즉, 이진 검색 중에 히트 한 페이지입니다.

    • 동시성 - 동일한 프로세스 공간에서 파일을 여러 번 메모리 맵핑 할 때 구현 문제가 발생했습니다. 이것은 때때로 시스템이 파일을 매핑하기에 충분한 크기의 가상 메모리 블록을 찾지 못해서 기억하기 때문에 문제였습니다. 해결책은 파일을 한 번만 매핑하고 모든 호출을 썽 크크하는 것입니다. 본격적인 Windows 서비스를 사용한 회상에서는 멋진 일이었습니다.
    • 랜덤 액세스 - 이진 검색은 확실히 임의 액세스 및 번개입니다.
    • 성능 - 조회가 매우 빠릅니다. 사용자가 입력 할 때 팝업 창에 일치하는 제품 부품 번호 목록이 표시되면 입력을 계속하면서 목록이 축소됩니다. 타이핑하는 동안 눈에 띄는 지연은 없습니다.
    +1

    시도 할 때마다 페이지를 읽을 때마다 검색 속도가 느려 집니까? 아니면 운영 체제가 효율적으로이를 처리 할만큼 똑똑합니까? – jjxtra

    +1

    메모리 맵핑 된 I/O를 사용하는 것이 바이너리 검색에 다소 낭비라고 생각합니다. 검색은 상대적으로 먼 메모리 위치에있는 몇 개의 키만 액세스 할 수 있지만, OS는 각 요청에 대해 4k 페이지를로드합니다. 그러나 다시 한 번, 부품이있는 파일은별로 변하지 않으므로 캐시가이를 덮어 씁니다. 그러나 엄밀히 말하면, 저는 전통적인 추구/독서가 여기에서 더 좋을 것이라고 믿습니다. 마지막으로 1 백만 달러는별로 요즘 없습니다. RAM에 모든 것을 보관하지 않는 이유는 무엇입니까? –

    +2

    @ 돼지와 PsychoDad 나의 원래 대답은 2008 년이었고이 메모리 매핑 된 자동 완성 기능의 실제 구현은 약 2004-2005 년 정도였습니다. 전체 파일을로드하는 데 800-1000MB의 실제 메모리를 사용하는 것이 우리 사용자에게 좋은 솔루션이 아니 었습니다. 메모리 매핑 된 솔루션은 매우 빠르고 효율적이었습니다. 그것은 엉덩이를 걷어차 며, 나는 초기의 주니어 개발자 시절부터 좋아하게 기억합니다. :) –

    관련 문제