Menu Close
Settings Close

Language and Page Formatting Options

13.6.4. vCPU 性能调整场景示例

为了获得最佳 vCPU 性能,红帽建议您同时使用手动 vcpupinemulatorpinnumatune 设置,如以下场景中所示:

起始场景

  • 您的主机有以下与硬件相关的信息:

    • 2 个 NUMA 节点
    • 每个节点上的 3 个 CPU 内核
    • 每个内核有 2 个线程

    此类机器的 virsh nodeinfo 输出类似于:

    # virsh nodeinfo
    CPU model:           x86_64
    CPU(s):              12
    CPU frequency:       3661 MHz
    CPU socket(s):       2
    Core(s) per socket:  3
    Thread(s) per core:  2
    NUMA cell(s):        2
    Memory size:         31248692 KiB
  • 您打算将现有的虚拟机修改为有 8 个 vCPU,这意味着单个 NUMA 节点无法容纳它。

    因此,您应该在每个 NUMA 节点上分发 4 个 vCPU,并使 vCPU 拓扑尽可能接近主机拓扑。这意味着,作为给定物理 CPU 的同级线程运行的 vCPU 应该固定到同一核上的主机线程。详情请查看以下解决方案:

解决方案

  1. 获取主机拓扑的信息:

    # virsh capabilities

    输出应包含类似如下的部分:

    <topology>
      <cells num="2">
        <cell id="0">
          <memory unit="KiB">15624346</memory>
          <pages unit="KiB" size="4">3906086</pages>
          <pages unit="KiB" size="2048">0</pages>
          <pages unit="KiB" size="1048576">0</pages>
          <distances>
            <sibling id="0" value="10" />
            <sibling id="1" value="21" />
          </distances>
          <cpus num="6">
            <cpu id="0" socket_id="0" core_id="0" siblings="0,3" />
            <cpu id="1" socket_id="0" core_id="1" siblings="1,4" />
            <cpu id="2" socket_id="0" core_id="2" siblings="2,5" />
            <cpu id="3" socket_id="0" core_id="0" siblings="0,3" />
            <cpu id="4" socket_id="0" core_id="1" siblings="1,4" />
            <cpu id="5" socket_id="0" core_id="2" siblings="2,5" />
          </cpus>
        </cell>
        <cell id="1">
          <memory unit="KiB">15624346</memory>
          <pages unit="KiB" size="4">3906086</pages>
          <pages unit="KiB" size="2048">0</pages>
          <pages unit="KiB" size="1048576">0</pages>
          <distances>
            <sibling id="0" value="21" />
            <sibling id="1" value="10" />
          </distances>
          <cpus num="6">
            <cpu id="6" socket_id="1" core_id="3" siblings="6,9" />
            <cpu id="7" socket_id="1" core_id="4" siblings="7,10" />
            <cpu id="8" socket_id="1" core_id="5" siblings="8,11" />
            <cpu id="9" socket_id="1" core_id="3" siblings="6,9" />
            <cpu id="10" socket_id="1" core_id="4" siblings="7,10" />
            <cpu id="11" socket_id="1" core_id="5" siblings="8,11" />
          </cpus>
        </cell>
      </cells>
    </topology>
  2. 可选: 使用 适用的工具和实用程序 测试虚拟机的性能。
  3. 在主机上设置并挂载 1 GiB 巨页:

    1. 在主机的内核命令行中添加以下行:

      default_hugepagesz=1G hugepagesz=1G
    2. 使用以下内容创建 /etc/systemd/system/hugetlb-gigantic-pages.service 文件:

      [Unit]
      Description=HugeTLB Gigantic Pages Reservation
      DefaultDependencies=no
      Before=dev-hugepages.mount
      ConditionPathExists=/sys/devices/system/node
      ConditionKernelCommandLine=hugepagesz=1G
      
      [Service]
      Type=oneshot
      RemainAfterExit=yes
      ExecStart=/etc/systemd/hugetlb-reserve-pages.sh
      
      [Install]
      WantedBy=sysinit.target
    3. 使用以下内容创建 /etc/systemd/hugetlb-reserve-pages.sh 文件:

      #!/bin/sh
      
      nodes_path=/sys/devices/system/node/
      if [ ! -d $nodes_path ]; then
      	echo "ERROR: $nodes_path does not exist"
      	exit 1
      fi
      
      reserve_pages()
      {
      	echo $1 > $nodes_path/$2/hugepages/hugepages-1048576kB/nr_hugepages
      }
      
      reserve_pages 4 node1
      reserve_pages 4 node2

      这会从 node1 保留 4 个 1GiB 巨页,并在 node2 中保留 4 个 1GiB 巨页。

    4. 使在上一步中创建的脚本可执行:

      # chmod +x /etc/systemd/hugetlb-reserve-pages.sh
    5. 在引导时启用巨页保留:

      # systemctl enable hugetlb-gigantic-pages
  4. 使用 virsh edit 命令编辑您要优化的虚拟机的 XML 配置,在本例中为 super-VM

    # virsh edit super-vm
  5. 用以下方法调整虚拟机的 XML 配置:

    1. 将虚拟机设置为使用 8 个静态 vCPU。使用 <vcpu/> 元素来执行此操作。
    2. 将每个 vCPU 线程固定到拓扑中镜像的对应主机 CPU 线程。为此,请在 <cputune> 部分中使用 <vcpupin/> 元素。

      请注意,如上面 virsh capabilities 工具所示,主机 CPU 线程在各自的内核中不是按顺序排序的。此外,vCPU 线程应固定到同一 NUMA 节点上最多可用的主机核集合。有关表图,请查看以下 示例拓扑 部分。

      步骤 a. 和 b. 的 XML 配置类似:

      <cputune>
        <vcpupin vcpu='0' cpuset='1'/>
        <vcpupin vcpu='1' cpuset='4'/>
        <vcpupin vcpu='2' cpuset='2'/>
        <vcpupin vcpu='3' cpuset='5'/>
        <vcpupin vcpu='4' cpuset='7'/>
        <vcpupin vcpu='5' cpuset='10'/>
        <vcpupin vcpu='6' cpuset='8'/>
        <vcpupin vcpu='7' cpuset='11'/>
        <emulatorpin cpuset='6,9'/>
      </cputune>
    3. 将虚拟机设置为使用 1 GiB 巨页:

      <memoryBacking>
        <hugepages>
          <page size='1' unit='GiB'/>
        </hugepages>
      </memoryBacking>
    4. 配置虚拟机的 NUMA 节点,使其使用主机上对应的 NUMA 节点的内存。要做到这一点,请在 <numatune/> 部分中使用 <memnode/> 元素:

      <numatune>
        <memory mode="preferred" nodeset="1"/>
        <memnode cellid="0" mode="strict" nodeset="0"/>
        <memnode cellid="1" mode="strict" nodeset="1"/>
      </numatune>
    5. 确保 CPU 模式设为 host-passthrough,且 CPU 在 passthrough 模式下使用缓存:

      <cpu mode="host-passthrough">
        <topology sockets="2" cores="2" threads="2"/>
        <cache mode="passthrough"/>

验证

  1. 确认生成的虚拟机 XML 配置包含类似如下内容:

    [...]
      <memoryBacking>
        <hugepages>
          <page size='1' unit='GiB'/>
        </hugepages>
      </memoryBacking>
      <vcpu placement='static'>8</vcpu>
      <cputune>
        <vcpupin vcpu='0' cpuset='1'/>
        <vcpupin vcpu='1' cpuset='4'/>
        <vcpupin vcpu='2' cpuset='2'/>
        <vcpupin vcpu='3' cpuset='5'/>
        <vcpupin vcpu='4' cpuset='7'/>
        <vcpupin vcpu='5' cpuset='10'/>
        <vcpupin vcpu='6' cpuset='8'/>
        <vcpupin vcpu='7' cpuset='11'/>
        <emulatorpin cpuset='6,9'/>
      </cputune>
      <numatune>
        <memory mode="preferred" nodeset="1"/>
        <memnode cellid="0" mode="strict" nodeset="0"/>
        <memnode cellid="1" mode="strict" nodeset="1"/>
      </numatune>
      <cpu mode="host-passthrough">
        <topology sockets="2" cores="2" threads="2"/>
        <cache mode="passthrough"/>
        <numa>
          <cell id="0" cpus="0-3" memory="2" unit="GiB">
            <distances>
              <sibling id="0" value="10"/>
              <sibling id="1" value="21"/>
            </distances>
          </cell>
          <cell id="1" cpus="4-7" memory="2" unit="GiB">
            <distances>
              <sibling id="0" value="21"/>
              <sibling id="1" value="10"/>
            </distances>
          </cell>
        </numa>
      </cpu>
    </domain>
  2. 可选: 使用 适用的工具和实用程序 测试虚拟机的性能来评估虚拟机优化的影响。

拓扑示例

  • 下表演示了 vCPU 和主机 CPU 之间的连接:

    表 13.1. 主机拓扑

    CPU 线程

    0

    3

    1

    4

    2

    5

    6

    9

    7

    10

    8

    11

    内核

    0

    1

    2

    3

    4

    5

    插槽

    0

    1

    NUMA 节点

    0

    1

    表 13.2. VM 拓扑

    vCPU 线程

    0

    1

    2

    3

    4

    5

    6

    7

    内核

    0

    1

    2

    3

    插槽

    0

    1

    NUMA 节点

    0

    1

    表 13.3. 合并主机和虚拟机拓扑

    vCPU 线程

     

    0

    1

    2

    3

     

    4

    5

    6

    7

    主机 CPU 线程

    0

    3

    1

    4

    2

    5

    6

    9

    7

    10

    8

    11

    内核

    0

    1

    2

    3

    4

    5

    插槽

    0

    1

    NUMA 节点

    0

    1

    在这种情况下,有 2 个 NUMA 节点和 8 个 vCPU。因此,应该为每个节点固定 4 个 vCPU 线程。

    另外,红帽建议在每个节点上至少保留一个 CPU 线程用于主机系统操作。

    因为在这个示例中,每个 NUMA 节点都有 3 个核,每个核都有 2 个主机 CPU 线程,节点 0 的设置转换如下:

    <vcpupin vcpu='0' cpuset='1'/>
    <vcpupin vcpu='1' cpuset='4'/>
    <vcpupin vcpu='2' cpuset='2'/>
    <vcpupin vcpu='3' cpuset='5'/>