전체 파일 시스템을 읽고 파일을 해싱하는 프로세스가 있습니다. 읽기로 인해 많은 조회가 발생하므로 속도가 느려집니다(약 4배). 각 파일의 작은 청크는 4개의 스레드 각각에서 읽히지만 복사(cp)를 통해 순차 읽기를 테스트하면 더 빨리 읽을 수 있습니다. CPU 사용률은 25%이므로 CPU 바인딩이 아닙니다. 나는 추구하는 것이 문제라고 확신합니다.
커널에는 액세스 속도를 높이기 위해 상당히 정교한 디스크 읽기 전략이 있다는 것을 읽었으므로 커널 버퍼가 여기서 사용을 제한하는지, 그리고 더 많은 버퍼링을 허용하도록 늘릴 수 있는지 궁금합니다. 나는 내가 사용하고 있는 프로그램이 각 읽기 호출에서 아주 작은 양의 데이터만 요청한다고 가정하고 있으므로 이것이 작동할지는 모르겠습니다.
각 파일을 정확히 하나씩 메모리로 읽는 것이 가장 효율적일 것이라고 생각하지만 지금은 응용 프로그램을 다시 작성할 수 없습니다(내 것이 아니며 크고 부풀어 오른 것처럼 보입니다). 그러나 OS가 각 파일을 순차적으로 읽도록 할 수 있습니까? 파일이 완전히(또는 부분적으로, 한 번에 100 - 500MB 정도) 버퍼에 열려 있으므로 애플리케이션 스레드는 작은 파일 각각만 사용합니다. 대신 메모리 읽기를 호출합니다. 디스크(탐색 결과)?
나중에 추가됨:
@Artem Caching은 여기서 작업을 수행하지 않는 것 같고 그 이유를 이해할 수 있다고 생각합니다. 커널은 "합리적"이려고 노력하며 "사용자가 첫 번째 MB를 요청했기 때문에 전체 500MB 파일을 메모리로 읽지 않을 것입니다"라고 말합니다. 이것은 의미가 있습니다. 로드된 콘텐츠는 캐시되므로 다시 사용되는 경우(예: 다른 프로세스에서) 메모리에서 가져올 수 있습니다. 그러나 내가 원하는 것은 커널이 첫 번째 읽기에서 전체 파일을 캐시에 로드하는 것입니다(첫 번째 읽기는 무엇입니까, 아마도 2MB입니까?).
따라서 시스템 호출이 읽혀집니다(fd, buf, size). 내가 프로그래밍을 하고 있다면 CI는 절대 크기만큼 큰 버퍼를 넣지 않을 것입니다. 많은 프로그래머들이 그렇게 할지는 의심스럽습니다. 따라서 아마도 보다 일반적인 버퍼 크기(1~2MB)를 사용하여 기록되었을 것입니다.
따라서 사용자 프로세스는 1~2MB를 얻고 해시 기능으로 이동하여 잠시 동안 바쁜 상태를 유지하고 디스크 읽기를 위해 커널을 괴롭히는 것을 중지합니다. 동시에 다른 디스크 읽기는 디스크의 다른 부분을 읽기 위해 다른 스레드에 의해 대기열에 추가됩니다. 따라서 이제 커널이 작동 중이고 디스크가 디스크의 다른 부분을 찾고 있는데, 이 작업에는 약 15밀리초가 걸립니다.
불행하게도 파일은 디스크의 상당히 큰 연속 블록에 저장되는 경우가 많습니다. 따라서 디스크에서 첫 번째 파일을 지속적으로 읽으면 탐색 없이 수십만, 심지어는 백만 블록, 수십 또는 수백 MB를 읽을 수 있습니다. 고성능 디스크 읽기는 제가 권장하고 싶은 것입니다.
하지만 그렇지 않습니다. 프로세스는 작은 데이터 덩어리를 요청하고 있고, 커널은 정상적인 상태를 유지하려고 노력하고 있으며 아무도 요청하지 않은 많은 양의 데이터를 읽지 않으려고 하며(그러면 대기 중인 프로세스가 차단됨) 결과적으로 주위를 둘러보고 있습니다. 미친 듯이 찾기 위해 모든 시간을 소비합니다.
"cp -r"과 대조됩니다. 단 1개의 스레드만 커널에 파일 읽기를 요청합니다. 따라서 아무도 디스크 헤드에 매 MB 또는 매 2 MB마다 디스크의 다른 부분을 찾도록 지시하지 않으므로 후속 읽기가 커널에 들어올 때 드라이브는 데이터를 빠르게 얻을 수 있습니다.
더 큰 버퍼로 코드를 다시 작성할 수 있으므로 이것이 나에게 옵션입니다. 하지만 앞서 말했듯이 커널에 "미리" 더 많은 버퍼링을 수행하도록 지시하는 것이 가능한지 알고 싶습니다. 일종의 "미리 읽기 캐시"와 같습니다. 일단 파일이 열리면 완전히 읽힐 것으로 예상되므로 각 파일에 대한 커널 버퍼를 읽기 위해 물리적 디스크를 중지하기 전에 읽기 버퍼가 최소 n 바이트로 채워집니다.
답변1
Linux 커널은 파일 시스템 캐싱에 사용 가능한 전체 RAM을 사용합니다. 더 이상 활용하게 할 수는 없습니다.
더 높은 swappiness 값을 사용해 볼 수도 있지만 99% 도움이 되지 않을 것이라고 확신합니다.
어쩌면 더 많은 메모리가 필요할 수도 있습니다.