Linux가 주기적으로 mmap 파일을 디스크에 동기화하는 것을 방지하는 동시에 물리적 메모리가 부족할 때 OS가 다시 쓸 수 있도록 허용하는 방법이 있는지 궁금합니다.
저는 대용량 이미지를 처리하는 애플리케이션을 작성 중입니다. 너무 커서 스왑 공간이 몇 배나 필요할 수 있습니다. 이로 인해 스왑 공간이 소진되면 예기치 않은 OOM 충돌이 발생할 수 있습니다.
스왑을 사용하지 않고 큰 메모리 개체를 할당하는 간단한 방법은 mmap()을 호출하는 것입니다. 이 호출은 사용이 매우 간단하고 잘 작동하지만 성능에 심각한 영향을 미치는 한 가지 주요 문제가 있습니다. 운영 체제는 주기적으로 mmap 영역에서 더티 페이지를 작성합니다.
내 애플리케이션의 경우 CPU 사용률이 약 2900%에서 약 700%로 감소하여 프로세스 속도가 4배 느려졌습니다.
과거에 RedHat은 운영 체제 매개변수 vm.flush_mapped_pages를 0으로 설정하여 이 동작을 끌 수 있도록 허용했지만 이 설정은 더 이상 존재하지 않으며 예기치 않은 동작이 발생할 수 있습니다. 정상적인 작업을 처리합니다.
FreeBSD에서는 mmap 호출에서 NO_SYNC 플래그를 사용하여 이 동작을 끌 수 있지만 Linux에서는 사용할 수 없습니다.
오류를 처리하고 EINTR을 제거하는 코드를 사용하여 mmap 버퍼를 생성하는 방법은 다음과 같습니다.
size_t n = 1048576*(size_t)1024*16; // 16G
int fd = open("mem.bin", O_TRUNC | O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
ftruncate(fd, n);
void* data = mmap(nullptr, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_HUGE_2MB, fd, 0);
close(fd);
unlink("mem.bin");
이 메모리를 효율적으로 사용할 수 있는 방법이 있나요?
답변1
vm.dirty_writeback_centisecs
sysctl을 0으로 설정하여 커널의 백그라운드 더티 페이지 새로 고침 스레드를 비활성화할 수 있습니다. 또한 vm.dirty_ratio
꼭 필요한 경우가 아니면 프로세스가 강제로 더티 쓰기 저장을 수행하지 않도록 늘려야 합니다 . 백그라운드 새로 고침 스레드가 비활성화된 경우 및 vm.dirty_background_ratio
sysctls 는 관련이 없습니다.vm.dirty_background_bytes
vm.dirty_expire_centisecs
안타깝게도 페이지별 또는 VMA별로 쓰기 저장 동작을 조정하는 것은 불가능하다고 생각합니다. 전체 VM 하위 시스템에 대해서만 조정할 수 있습니다.