IOThread Virtqueue 매핑을 사용한 virtio-blk 디스크 I/O 확장

Red Hat Blog를 보다가 관심 가는 글이 보여서 AI번역+약간 교정해 보았습니다.
출처: https://developers.redhat.com/articles/2024/09/05/scaling-virtio-blk-disk-io-iothread-virtqueue-mapping

이 문서에서는 Red Hat Enterprise Linux (RHEL) 9.4 에 도입된 커널 기반 가상 머신(KVM) 게스트를 위한 IOThread Virtqueue 매핑 기능에 대해 설명합니다 .

문제

최신 스토리지는 I/O 요청을 전송할 수 있는 여러 개의 큐를 제공함으로써 증가하는 CPU 수에 발맞춰 발전했습니다. 이를 통해 CPU는 I/O 요청을 전송하고 완료 인터럽트를 로컬에서 처리할 수 있습니다. 결과적으로 여러 CPU가 장착된 시스템에서 우수한 성능과 확장성을 제공합니다.

KVM 게스트의 virtio-blk 장치는 기본적으로 여러 개의 대기열을 가지지만, 호스트의 다중 대기열 기능을 활용하지는 않습니다.  <driver io=native …> libvirt 도메인 XML 설정이 적용된 게스트의 경우, 모든 대기열의 I/O 요청은 호스트의 단일 스레드에서 처리됩니다. 이 단일 스레드는 I/O 중심 워크로드의 병목 현상이 될 수 있습니다.

KVM 게스트는 이제 새로운 IOThread Virtqueue 매핑 기능을 통해 단일 장치에 대해 여러 호스트 스레드를 활용할 수 있습니다. 이를 통해 단일 스레드가 병목 현상을 일으키는 워크로드의 I/O 성능이 향상됩니다. vCPU가 많은 게스트는 이 기능을 사용하여 여러 스레드를 통해 제공되는 추가 용량을 활용할 수 있습니다.

이 기능 개발에 관련된 QEMU 내부 구조에 관심이 있으시면  이 블로그 게시물 과  KVM 포럼 프레젠테이션 에서 더 자세히 알아보실 수 있습니다 . QEMU의 블록 계층을 스레드로부터 안전하게 만드는 것은 엄청난 작업이었고, 저희는 이를 업스트림에서 기여할 수 있어서 자랑스럽게 생각합니다.

IOThread Virtqueue 매핑 작동 방식

IOThread Virtqueue 매핑을 사용하면 사용자가 IOThread 라는 호스트 스레드에 개별 virtqueue를 할당하여  virtio-blk 장치를 여러 스레드에서 처리할 수 있습니다. 각 virtqueue는 하나의 IOThread에 할당될 수 있습니다.

대부분의 사용자는 가상 큐가 IOThread 집합에 자동으로 분산되도록 라운드 로빈 할당을 선택합니다. 그림 1은 4개의 큐가 2개의 IOThread에 라운드 로빈 방식으로 할당되는 방식을 보여줍니다.

두 개의 IOThread에 할당된 네 개의 큐가 있는 virtio-blk 장치의 그림입니다. 큐 1과 큐 3은 녹색이며 IOThread 1에 할당되어 있습니다. 큐 2와 큐 4는 빨간색이며 IOThread 2에 할당되어 있습니다.
그림 1: 2개의 IOThread에 할당된 4개의 대기열이 있는 virtio-blk 장치.

이 구성에 대한 libvirt 도메인 XML은 다음과 같습니다.

<domain>
  …
  <vcpu>4</vcpu>
  <iothreads>2</iothreads>
  …
  <devices>
    <disk …>
      <driver name='qemu' cache=’none’ io=’native’ …>
        <iothreads>
          <iothread id='1'></iothread>
          <iothread id='2'></iothread>
        </iothreads>

구문에 대한 자세한 내용은  libvirt 설명서 에서 확인할 수 있습니다 .

구성 팁

다음 권장 사항은 이 기능을 개발하고 벤치마킹한 경험에 따른 것입니다.

  • 4~8개의 IOThread를 사용하세요. 일반적으로 이 정도면 디스크가 포화 상태에 도달하기에 충분합니다. 포화 상태를 넘어서 스레드를 추가해도 성능 향상에는 도움이 되지 않으며 오히려 해로울 수 있습니다.
  • 특정 기기의 사용량이 많다는 것을 미리 알고 있지 않는 한, 기기 간에 IOThread를 공유하세요 . 몇 개의 IOThread를 바쁘게 사용하되 너무 바쁘지 않게 유지하는 것이 이상적입니다.
  • 호스트 CPU에 여유가 있다면 <iothreadpin> 및 <vcpupin>을 사용하여 IOThread를 vCPU에서 분리하십시오. 게스트가 I/O를 제출할 때 IOThread는 신속하게 응답해야 합니다. 따라서 게스트의 vCPU 스레드와 CPU 시간을 경쟁해서는 안 됩니다.
  • <driver io=”native” cache=”none” …>을 사용하십시오. IOThread Virtqueue 매핑은 io=”native”를 위해 설계되었습니다. io=”threads”는 IOThread Virtqueue 매핑과 유용하게 결합되지 않으므로 권장하지 않습니다.

성능

다음 랜덤 읽기 디스크 I/O 벤치마크는 IOThread Virtqueue 매핑이 2개 및 4개일 때와 IOThread Virtqueue 매핑이 없는 게스트(IOThread가 1개만 있음)를 비교합니다. 게스트는 8개의 vCPU가 모두 병렬로 I/O를 전송하도록 구성되었습니다. 그림 2를 참조하십시오.

IOThread Virtqueue 매핑이 2개 및 4개인 경우와 IOThread Virtqueue 매핑이 없는 게스트(IOThread가 1개만 있는 경우)를 비교하는 랜덤 읽기 디스크 I/O 벤치마크를 나타내는 막대 그래프입니다. y축은 iops, x축은 iodepth로 표시됩니다.
그림 2: 1, 2, 4 IOThread를 비교할 때 IOPS가 증가하는 iodepth 1 및 64에 대한 무작위 읽기 4KB 벤치마크 결과입니다.

가장 중요한 fio벤치마크 옵션은 다음과 같습니다.

fio --ioengine=libaio –rw=randread –bs=4k --numjobs=8 --direct=1 --cpus_allowed=0-7 --cpus_allowed_policy=split

이 마이크로벤치마크는 하나의 IOThread가 디스크를 포화시킬 수 없을 때, IOThread Virtqueue 매핑을 사용하여 IOThread를 추가하면 상당한 성능 향상을 얻을 수 있음을 보여줍니다. Virtqueue는 IOThread에 라운드 로빈 방식으로 할당되었습니다. 디스크는 Intel Optane SSD DC P4800X였고, 게스트는 Fedora 39 x86_64를 실행했습니다. libvirt 도메인 XML, fio 옵션, 벤치마크 출력 및 Ansible 플레이북은  여기에서 확인할 수 있습니다 .

실제 워크로드는 I/O 바인딩 정도와 여러 vCPU에서 I/O를 전송하는지 여부에 따라 성능이 저하될 수 있습니다. IOThread Virtqueue 매핑의 효과를 파악하기 위해 워크로드를 벤치마킹하는 것이 좋습니다.

동반 문서에서는 IOThread Virtqueue 매핑을 사용한 데이터베이스 성능에 대해 살펴봅니다.

결론

RHEL 9.4의 새로운 IOThread Virtqueue 매핑 기능은 여러 vCPU를 사용하는 게스트의 디스크 I/O 확장성을 향상시킵니다. virtio-blk 장치가 있는 KVM 게스트에서 이 기능을 활성화하면 I/O 중심 워크로드의 성능을 향상시킬 수 있습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

You May Also Like