메모리 매핑 파일의 장점은 무엇입니까?


89

저는 프로젝트를 위해 메모리 매핑 파일을 연구 해 왔으며 이전에 사용했거나 사용하지 않기로 결정한 사람들의 의견을 고맙게 생각하며 그 이유는 무엇입니까?

특히 다음 사항이 중요합니다.

  • 동시성
  • 랜덤 액세스
  • 공연
  • 사용의 용이성
  • 휴대 성

답변:


56

기존의 파일 읽기 방법에 비해 필요한 데이터 복사량을 줄이는 것이 장점이라고 생각합니다.

응용 프로그램이 메모리 매핑 된 파일의 "제자리"에서 데이터를 사용할 수 있으면 복사하지 않고도 가져올 수 있습니다. 시스템 호출 (예 : Linux의 pread ())을 사용하는 경우 일반적으로 커널이 자체 버퍼에서 사용자 공간으로 데이터를 복사하는 작업이 포함됩니다. 이 추가 복사는 시간이 소요될뿐만 아니라이 추가 데이터 사본에 액세스하여 CPU 캐시의 효율성을 감소시킵니다.

실제로 디스크에서 데이터를 읽어야하는 경우 (물리적 I / O에서와 같이) OS는 여전히 데이터를 읽어야합니다. 페이지 오류는 시스템 호출보다 성능면에서 더 좋지 않을 수 있습니다. 하지 마십시오 (예 : 이미 OS 캐시에 있음). 이론상 성능이 훨씬 좋아야합니다.

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


메모리 매핑 파일의 명백한 단점은 32 비트 OS에 있다는 것입니다. 주소 공간이 쉽게 부족해질 수 있습니다.


4
Windows에서는 적어도 더 큰 mmap 파일의 여러 32 비트 뷰를 매핑 할 수 있습니다. 이는 일반 CRT 기능을 사용하여 매우 큰 파일을 처리하는 것보다 더 효율적일 수 있습니다
Martin Beckett 2011

@MarkR "그의 추가 복사는 시간이 걸릴뿐만 아니라이 추가 데이터 사본에 액세스하여 CPU 캐시의 효율성을 감소시킵니다. "라고 썼습니다 . ( 내 강조 ). 커널의 추가 버퍼 복사가 CPU 캐시의 효율성을 어떻게 방해하는지 설명해 주시겠습니까?
Geek

4
@Geek가 두 배의 메모리에 액세스하면 낭비되는 캐시의 두 배 (대략적으로).
user253751

49

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

런타임에 파일은 메모리 매핑되고 C스타일 struct배열로 캐스트 되며 사용자가 입력 할 때 일치하는 부품 번호를 찾기 위해 이진 검색을 수행합니다. 파일의 몇 개의 메모리 페이지 만 실제로 디스크에서 읽습니다.

  • 동시성-때때로 동일한 프로세스 공간에서 파일을 여러 번 메모리 맵하는 구현 문제가있었습니다. 때때로 시스템이 파일을 매핑 할 수있는 충분한 가상 메모리 블록을 찾을 수 없기 때문에 이것은 제가 기억하는 문제였습니다. 해결책은 파일을 한 번만 매핑하고 모든 호출을 처리하는 것입니다. 돌이켜 보면 완전한 Windows 서비스를 사용하는 것이 멋 졌을 것입니다.
  • 랜덤 액세스-이진 검색은 확실히 랜덤 액세스이며 번개처럼 빠릅니다.
  • 성능-조회가 매우 빠릅니다. 사용자가 팝업 창에 일치하는 제품 부품 번호 목록을 표시하면 입력을 계속하면 목록이 축소됩니다. 입력하는 동안 눈에 띄는 지연이 없습니다.

1
이진 검색은 각 시도에 대해 페이지를 읽을 때 느리지 않습니까? 아니면 운영 체제가이를 효율적으로 처리 할 수있을만큼 똑똑합니까?
jjxtra 2013

1
메모리 매핑 된 I / O를 사용하는 것은 검색이 상대적으로 먼 메모리 위치에있는 몇 개의 단일 키에만 액세스 할 수 있기 때문에 이진 검색에 다소 낭비 적이라고 생각하지만 OS는 각 요청에 대해 4k 페이지로로드됩니다. 그러나 부분이있는 파일은 많이 변경되지 않으므로 캐시가이를 은폐하는 데 도움이됩니다. 하지만 엄밀히 말해서, 저는 전통적인 찾기 / 읽기가 여기서 더 나을 것이라고 믿습니다. 마지막으로, 요즘 1 백만은 많지 않습니다. 왜 모든 것을 RAM에 보관하지 않습니까?
돼지

5
@the swine과 PsychoDad의 원래 대답은 2008 년이었고이 메모리 매핑 자동 완성 기능의 실제 구현은 2004-2005 년 정도였습니다. 800-1000MB의 실제 메모리를 사용하여 전체 파일을로드하는 것은 사용자 기반에 좋은 솔루션이 아닙니다. 메모리 매핑 솔루션은 매우 빠르고 효율적이었습니다. 초반 개발자 시절부터 멋지게 기억합니다. :)
Brian Ensink

@BrianEnsink : 알겠습니다. 나는 각 항목이 1kB만큼 될 것이라고 기대하지 않았습니다. 물론 페이징 방식이 더 효율적으로 변합니다. 좋은 :)
돼지

22

메모리 매핑 파일은 읽기 / 쓰기 액세스를 대체하거나 동시 공유를 지원하는 데 사용할 수 있습니다. 한 메커니즘에 사용하면 다른 메커니즘도 얻게됩니다.

파일을 찾고 쓰고 읽는 대신 메모리에 매핑하고 예상되는 비트에 액세스하기 만하면됩니다.

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

매핑 된 메모리를 통해 동일한 "파일"을 사용하는 여러 프로세스의 가능성을 고려할 때 동시성이 나타납니다. 읽기 / 쓰기 모델에서 두 프로세스가 파일의 동일한 영역에 쓴 경우 프로세스의 데이터 중 하나가 파일에 도착하여 다른 프로세스의 데이터를 덮어 쓰는 것이 거의 확실합니다. 당신은 하나 또는 다른 것을 얻을 수 있지만 이상한 혼합은 아닙니다. 나는 이것이 어떤 표준에서 요구하는 행동인지 확실하지 않지만 당신이 거의 의지 할 수있는 것임을 인정해야합니다. (실제로 좋은 후속 질문입니다!)

대조적으로, 매핑 된 세계에서 "쓰기"두 가지 과정을 상상해보십시오. 그들은 "메모리 저장소"를 수행하여이를 수행하며 결과적으로 O / S가 데이터를 디스크로 페이징합니다. 그러나 그 동안 겹치는 쓰기가 발생할 수 있습니다.

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

11111111
22222222
11112222
22221111

이에 대한 해결책은 명시 적 상호 배제를 사용하는 것입니다. 이는 어떤 경우에도 좋은 생각입니다. 어쨌든 읽기 / 쓰기 파일 I / O의 경우 "올바른 일"을 수행하기 위해 O / S에 의존하고있었습니다.

분류 상호 배제 프리미티브는 뮤텍스입니다. 메모리 매핑 파일의 경우 pthread_mutex_init ()를 사용하여 사용할 수있는 메모리 매핑 된 뮤텍스를 살펴 보는 것이 좋습니다.

단 하나의 문제로 편집 : 매핑 된 파일을 사용할 때 파일 자체에있는 데이터에 대한 포인터를 포함하려는 유혹이 있습니다 (매핑 된 파일에 저장된 연결 목록을 생각해보십시오). 파일이 다른 시간 또는 다른 프로세스에서 다른 절대 주소에 매핑 될 수 있으므로 그렇게하고 싶지 않습니다. 대신 매핑 된 파일 내에서 오프셋을 사용하십시오.


1

동시성이 문제가 될 것입니다. 랜덤 액세스가 더 쉬움 성능이 우수합니다. 사용의 용이성. 그다지 좋지 않습니다. 휴대 성-그렇게 뜨겁지 않습니다.

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.