파일 I/O 속도 향상: mmap() vs read()
150-200개의 파일(4-10GB)을 병렬로 읽는 Linux 애플리케이션이 있습니다.각 파일은 일반적으로 각각 2K 미만의 작은 가변 크기 블록으로 차례로 읽힙니다.
현재 파일 집합에서 합쳐 200MB/s 이상의 읽기 속도를 유지해야 합니다.디스크가 이 문제를 잘 처리합니다.1GB/s 이상의 예상 요구사항이 있습니다(현재로서는 디스크를 사용할 수 없습니다).
우리는 두 가지 다른 읽기 시스템을 구현했습니다. 둘 다 매우 많이 사용합니다.posix_advise
는 첫째는입니다.mmap
전체 데이터 세트를 매핑하고 온디맨드로 읽는 Ed read.는 두째는입니다.read()
/seek()
기반 시스템
다 잘 둘다잘작동정경작중만다동니합우에도의간만지하▁both▁the▁well다작니▁for▁the동합,▁cases▁only.read()
인 파일 더 잘을 잘 처리할 수 가 심하게 제한되어 .mmap
200MB/s 속도를 세트 가 큰 할 수 없습니다.200MB/s 이데전속송유도지를사있를수터캐없다수니습처할리경큰는에크우세전가기데트체터이만슁할기지리전하이관도쉽이록데터인상지적속의200▁is없다▁making니습수할처리▁sizesmb▁able▁data▁rate는▁deal에▁with▁large경우▁but▁set,mb▁of큰▁data▁total▁pre▁the▁cannot▁data▁200-▁overcache크▁to가▁sustained기세▁maintain▁easy전
그래서 제 질문은 다음과 같습니다.
A: 캔read()
i는 type file i/o를 됩니다.posix_advise
Linux에서 호출하거나 디스크 스케줄러, VMM 및 posix_advise 호출을 조정한 것이 기대만큼 좋습니까?
B: 매우 큰 매핑 데이터를 더 잘 처리할 수 있는 체계적인 방법이 있습니까?
Mmap-vs-reading-blocks는 제가 일하고 있는 것과 유사한 문제이며 mmap-vs-read의 논의와 함께 이 문제에 대한 좋은 출발점을 제공했습니다.
뭘 다시 읽나요?이 데이터의 최종 목적지는 어디입니까?
묶인 에 IO와 IO는 서로 연결되어 .mmap
그리고.read
차이가 없어야 합니다.흥미로운 부분은 데이터를 수신기로 가져오는 방법입니다.
이 데이터를 파이프에 넣는다고 가정하면 각 파일의 전체 내용을 파이프에 덤프하는 것이 좋습니다.제로 복사를 사용하여 이 작업을 수행하려면 시스템 호출을 시도하십시오.파일을 수동으로 복사하거나 인스턴스를 포킹할 수도 있습니다.cat
또는 현재 파일을 stdin으로, 파이프를 stdout으로 많이 버퍼링할 수 있는 다른 도구.
if (pid = fork()) {
waitpid(pid, ...);
} else {
dup2(dest, 1);
dup2(source, 0);
execlp("cat", "cat");
}
업데이트 0
처리가 파일에 구애받지 않고 임의 액세스가 필요하지 않은 경우 위에 설명된 옵션을 사용하여 파이프라인을 만들 수 있습니다.처리 단계에서는 표준 편차 또는 파이프의 데이터를 수락해야 합니다.
보다 구체적인 질문에 답변하려면:
A: Linux에서 posix_advise 호출을 초과하여 read() 유형의 파일 i/o를 추가로 최적화할 수 있습니까? 아니면 디스크 스케줄러, VMM 및 posix_advise 호출을 조정한 것이 우리가 기대하는 것만큼 좋습니까?
커널에 사용자 공간에서 수행할 작업을 지시하는 것과 관련하여 이는 매우 유용합니다.나머지는 버퍼링, 스레드화 등 여러분에게 달려 있지만 위험하고 아마도 비생산적인 추측 작업일 것입니다.저는 그냥 파이프에 파일을 스플라이싱하는 것으로 하겠습니다.
B: 매우 큰 매핑 데이터를 더 잘 처리할 수 있는 체계적인 방법이 있습니까?
예. 다음과 같은 옵션을 사용하면 성능 면에서 큰 이점을 얻을 수 있습니다(또한 테스트를 통해 mmap을 덮어쓸 수도 있습니다).
MAP_HUGETLB
큰 페이지를 사용하여 매핑을 할당합니다.이렇게 하면 커널의 페이징 오버헤드가 감소하며, 기가바이트 크기의 파일을 매핑하는 경우 유용합니다.
MAP_NORESERVE
이 매핑에 대해 스왑 공간을 예약하지 마십시오.스왑 공간이 예약된 경우 매핑을 수정할 수 있다는 보장이 있습니다.스왑 공간이 예약되지 않은 경우 사용 가능한 물리적 메모리가 없는 경우 쓰기 시 SIGSEGV가 발생할 수 있습니다.이렇게 하면 전체 매핑에 필요한 물리적 메모리 + 스왑이 충분하지 않은 경우 구현을 단순하게 유지하면서 메모리가 부족해지는 것을 방지할 수 있습니다.**
MAP_POPULATE
매핑에 대한 페이지 테이블을 채웁니다(기본값).파일 매핑의 경우 파일에서 미리 읽기가 발생합니다.이후의 매핑 액세스는 페이지 오류로 인해 차단되지 않습니다.이렇게 하면 충분한 하드웨어 리소스를 사용하여 속도를 높일 수 있으며, 프리페치가 주문되어 있으면 속도가 느려질 수 있습니다.이 플래그가 중복된 것으로 의심됩니다. VFS는 기본적으로 이 기능을 더 잘 수행합니다.
프로그램이 읽고 싶은 파일 조각을 미리 예측할 수 있다면 미리 읽기 시스템 호출을 사용하는 것이 도움이 될 수도 있습니다(그러나 이것은 추측일 뿐입니다, 제가 틀릴 수도 있습니다).
그리고 저는 당신이 당신의 애플리케이션과 아마도 당신의 알고리즘을 조정해서 몇 킬로바이트보다 훨씬 더 큰 덩어리의 데이터를 읽어야 한다고 생각합니다.대신 0.5메가바이트 이상은 안 되나요?
여기서 문제는 어떤 api가 사용되는지가 아닌 것 같습니다.mmap()을 사용하든 read()를 사용하든 상관없이 디스크는 여전히 지정된 지점을 찾아 데이터를 읽어야 합니다(OS가 액세스를 최적화하는 데 도움이 되지만).
mmap()은 매우 작은 청크(2바이트)를 읽을 때 read()보다 장점이 있습니다. 왜냐하면 모든 청크에 대해 os를 호출하지 않기 때문입니다. 이는 매우 느려집니다.
저는 또한 Basile이 연속적으로 2kb 이상을 읽었기 때문에 디스크가 그렇게 자주 찾지 않아도 된다고 조언하고 싶습니다.
언급URL : https://stackoverflow.com/questions/8056984/speeding-up-file-i-o-mmap-vs-read
'programing' 카테고리의 다른 글
속성을 바인딩할 수 없습니다. (0) | 2023.06.21 |
---|---|
과부하 특성 라라벨 MongoDB의 간접 수정 (0) | 2023.06.21 |
Git API 바인딩이 가장 좋은 언어는 무엇입니까? (0) | 2023.06.21 |
HTTP 모듈 이벤트 실행 순서? (0) | 2023.06.11 |
쉼표로 숫자 형식을 지정하는 오라클 SQL 쿼리 (0) | 2023.06.11 |