저는 쓰기 처리량이 서로 다른 여러 저장 장치가 있는 시스템에서 작업하고 있습니다. 질문에 설명된 대로2013년에 "USB 플래시 드라이브 정지" 문제가 발생한 이유는 무엇입니까? 기존의 "I/O 더티 스로틀링 없음" 코드가 이 문제를 해결하지 못하는 이유는 무엇입니까?기본적으로 Linux에서는 단일 느린 장치가 쓰기 버퍼링을 위해 거의 모든 디스크 캐시를 사용할 수 있도록 허용합니다. 이로 인해 다른 장치에 쓰는 경우에도 모든 프로세스의 성능이 저하됩니다. 프로세스가 전체 캐시를 쓰기 위해 지연을 사용하는 경우 void sync(void)
상황은 더욱 악화됩니다 . 예를 들어 프로세스가 느린 USB 스틱에 ISO 이미지를 쓰는 경우 프로세스 시작부터 전체 이미지가 커널 캐시에 있을 수 있으므로 결국 sync()
전체 ISO 이미지가 느린 USB 스틱에 기록될 때까지 기다리게 됩니다. 막대.
프로세스 호출이 없더라도 void sync(void)
현재 시스템 전체 쓰기 캐시가 바이트를 초과하면 모든 프로그램이 평소처럼 백그라운드 쓰기 대신 동기 쓰기를 사용해야 하기 때문에 모든 프로그램이 느려집니다 /proc/sys/vm/dirty_background_bytes
.
단일(또는 병렬로 실행되는 여러 개) 느린 저장 장치로 인해 전체 시스템 속도가 느려지는 것을 방지하여 이러한 현상을 방지할 수 있기를 바랍니다. 내가 아는 한, 이를 위해서는 단일 느린 장치에 대한 쓰기 버퍼의 캐시 사용을 제한해야 합니다. 캐시는 느린 장치와 빠른 장치가 이러한 장치를 사용하는 모든 프로세스에 대해 병목 현상이 발생하도록 충분히 커야 하지만 기본 구성에서 발생하는 것처럼 해당 프로세스는 다른 장치에 의해 제한되지 않습니다.
/proc/sys/vm/dirty_background_bytes
50MB와 200MB로 제한하면 /proc/sys/vm/dirty_bytes
시스템의 대기 시간이 크게 나빠지지는 않았지만 느린 장치에 쓸 때 여전히 속도가 느려지는 것을 발견했습니다. 50MB 이상의 더티 캐시를 사용하면 모든 쓰기가 강제로 동기화되기 때문에 이런 일이 발생한다고 생각합니다. 느린 메모리에 쓰는 프로세스의 캐시가 52MB이고 다른 프로세스가 다른 빠른 SSD 장치에 4KB 파일을 쓰려고 한다고 가정하면 해당 4KB 쓰기도 동기화되어야 하며 이로 인해 SSD 장치 속도가 저하됩니다. RAM 속도로 실행되는 대신 속도가 느려집니다. 반면에 매우 빠른 SSD 장치에 쓸 때는 데이터를 생성하는 프로세스가 캐시를 채울 만큼 빠르지 않기 때문에 최대 200MB 쓰기 캐시가 너무 작을 수 있습니다. 따라서 이러한 두 가지 핵심 설정을 심각하게 제한하는 것은 최악의 대기 시간을 피하면서 최적이 아닌 평균 성능을 얻는 균형을 이루는 것입니다.
장치 BDI를 max_ratio
보다 작은 값으로 설정하면 100
해당 값이 해당 장치에 사용 가능한 전체 쓰기 캐시의 백분율로 사용된다는 것을 알고 있습니다.
그러나 모든 장치의 기본 설정은 100
느린 장치로 인해 전체 시스템이 느려지는 것을 허용하는 것입니다. max_ratio
아래와 같이 값을 설정하면 100
잘 작동하고 장치가 모든 캐시를 낭비할 수 없기 때문에 느린 장치로 인한 속도 저하를 방지하는지 테스트했습니다 .
향후 연결되는 장치를 포함하여 모든 장치에 대해 max_ratio
보다 작은 값을 설정하려면 어떻게 해야 합니까?100
시스템 부팅 중에 실행되고 연결된 모든 장치를 구성하는 스크립트를 작성할 수 있지만 새로 연결된 저장소(USB, eSATA 또는 기타 연결 방법)는 모든 쓰기 캐시를 가져오도록 허용됩니다.
답변1
max_ratio
모든 장치에 대한 규칙을 구성하고 사용할 수 있습니다 . 예를 들어, 내용과 함께 이름이 다음과 같은 새 파일을 만들 수 있습니다.min_ratio
udev
/etc/udev/rules.d/90-bdi-set-min_ratio-and-max_ratio.rules
root
# For every BDI device, set max cache usage to 30% and min reserved cache to 2% of the whole cache
ACTION=="add|change", SUBSYSTEM=="bdi", ATTR{min_ratio}="2", ATTR{max_ratio}="30"
(파일의 구문은 현재 상태를 확인하고 조치를 적용하는 것 *.rules
입니다 . 이 경우 모니터링 하위 시스템에 알리고 장치가 추가되거나 변경될 때마다 규칙 및 .==
=
udev
bdi
ATTR{min_ratio}="2"
ATTR{max_ratio}="30"
파일이 생성되면 시스템을 재부팅하거나 실행하여 sudo udevadm trigger
새 규칙을 적용할 수 있습니다. (이것은 Ubuntu 18.04 이상에서 작동하며 명령을 sudo udevadm control --reload-rules
실행하기 전에 일부 이전 버전을 실행해야 할 수도 있습니다.)trigger
다음 명령을 사용하면 모든 장치의 현재 상태를 확인할 수 있습니다.
$ grep . /sys/devices/virtual/bdi/*/{min,max}_ratio
위 예의 값(2 및 30)을 사용하면 시스템이 특정 장치에 대해 최소 2%의 캐시를 예약하고 단일 장치가 허용되는 최대 캐시의 최대 30%를 사용할 수 있도록 허용합니다. 3개의 저장 장치가 있고 이를 50으로 설정하면 어떤 일이 일어날지 모르겠습니다 min_ratio
. 논리적으로 해당 장치에 대해 전체 캐시 공간의 150%를 예약해야 하기 때문입니다. 이것을 테스트한다면 아래에 설명을 추가하십시오.
huge 및 값 설정과 어떻게 상호 작용하는지 테스트하지는 않았지만 dirty_bytes
커널 동작을 올바르게 이해하면 dirty_background_bytes
쓰기 캐시에 최소 (+)/바이트 또는 이 값 합계의 50%가 포함될 때까지 이러한 제한이 적용되지 않습니다. 따라서 대규모 캐시가 허용되는 경우 매우 낮은 비율을 설정하면 시스템이 캐싱을 위해 많은 RAM을 사용하는 것을 실제로 방지할 수 없습니다. 코어가 항상 쓰기 캐시에 + 합계의 절반을 사용한다고 가정하면 나머지 절반의 균형을 맞출 수 있습니다. 향후 커널에서는 이 기능이 향상될 수 있지만 제가 올바르게 이해한다면 커널 개발자는 모든 것이 원활하게 실행될 때 쓰기 캐시의 어느 부분이 어느 장치에 사용되는지 추적하는 오버헤드를 줄이기 위해 현재 구현을 사용합니다.dirty_bytes
dirty_background_bytes
2
min_ratio
max_ratio
dirty_bytes
dirty_background_bytes
min_ratio
느린 장치가 해당 장치 대신 캐시를 사용하는 것을 방지하기 위해 성능이 실제로 중요한 모든 장치만 향상시키는 것이 더 좋지만 커널 동작을 더 잘 이해하려면 더 많은 벤치마킹이 필요합니다. 내가 선택한 max_ratio
값은 30
최대 3개의 느린 장치가 병렬로 작동하도록 허용하고 여전히 빠른 장치에 사용할 수 있는 캐시의 10%를 갖습니다(아직 대역폭이 제한되지 않음). 커널은 기본적으로 캐시의 절반을 사용하고 max_ratio
나머지 절반의 균형을 유지하므로 사실상 제한이 0.5 + 0.5 * 0.3 또는 단일 느린 장치에 허용되는 최대 디스크 캐시의 약 65%로 설정됩니다.
파티션이나 전체 장치에 BDI 제한을 적용할 수 있습니다. RAID의 경우 RAID 내의 개별 파티션, 전체 RAID 장치 또는 RAID 내의 개별 장치에 BDI 제한을 적용할 수 있다고 가정합니다. 위 udev
스크립트는 모든 레벨에 제한을 적용합니다. 이것이 최적인지 확실하지 않습니다. 기본 장치에만 제한을 적용하는 것이 가장 좋습니다.