[PATCH 1/4] conf: Introduce memory allocation threads

Michal Privoznik mprivozn at redhat.com
Tue Mar 22 15:05:14 UTC 2022


Since its commit v5.0.0-rc0~75^2~1^2~3 QEMU is capable of
specifying number of threads used to allocate memory. While it
defaults to the number of vCPUs, users might want to use a
different value (especially for humongous guests with gigantic
pages).

In general, on QEMU cmd line level it is possible to use
different number of threads per each memory-backend-* object, in
practical terms it's not useful. Therefore, use <memoryBacking/>
to set guest wide value and let all memory devices 'inherit' it,
silently. IOW, don't introduce per device knob because that would
only complicate things for a little or no benefit.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 docs/formatdomain.rst                        |  6 ++++--
 docs/schemas/domaincommon.rng                | 19 +++++++++++++------
 src/conf/domain_conf.c                       | 15 ++++++++++++++-
 src/conf/domain_conf.h                       |  1 +
 tests/qemuxml2argvdata/memfd-memory-numa.xml |  2 +-
 5 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 9b1b69bb4d..8e25474db0 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -1004,7 +1004,7 @@ Memory Backing
        <locked/>
        <source type="file|anonymous|memfd"/>
        <access mode="shared|private"/>
-       <allocation mode="immediate|ondemand"/>
+       <allocation mode="immediate|ondemand" threads='8'/>
        <discard/>
      </memoryBacking>
      ...
@@ -1054,7 +1054,9 @@ influence how virtual memory pages are backed by host pages.
    "private". This can be overridden per numa node by ``memAccess``.
 ``allocation``
    Using the ``mode`` attribute, specify when to allocate the memory by
-   supplying either "immediate" or "ondemand".
+   supplying either "immediate" or "ondemand". :since:`Since 8.2.0` this
+   attribute is optional among with ``threads`` attribute, that sets the number
+   of threads that hypervisor uses to allocate memory.
 ``discard``
    When set and supported by hypervisor the memory content is discarded just
    before guest shuts down (or when DIMM module is unplugged). Please note that
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9c1b64a644..34bccee2f5 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -740,12 +740,19 @@
             </optional>
             <optional>
               <element name="allocation">
-                <attribute name="mode">
-                  <choice>
-                    <value>immediate</value>
-                    <value>ondemand</value>
-                  </choice>
-                </attribute>
+                <optional>
+                  <attribute name="mode">
+                    <choice>
+                      <value>immediate</value>
+                      <value>ondemand</value>
+                    </choice>
+                  </attribute>
+                </optional>
+                <optional>
+                  <attribute name="threads">
+                    <ref name="unsignedInt"/>
+                  </attribute>
+                </optional>
               </element>
             </optional>
             <optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e0dfc9e45f..2414a806d0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -18914,6 +18914,13 @@ virDomainDefParseMemory(virDomainDef *def,
         VIR_FREE(tmp);
     }
 
+    if (virXPathUInt("string(./memoryBacking/allocation/@threads)",
+                     ctxt, &def->mem.allocation_threads) == -2) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Failed to parse memory allocation threads"));
+        return -1;
+    }
+
     if (virXPathNode("./memoryBacking/hugepages", ctxt)) {
         /* hugepages will be used */
         if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt, &nodes)) < 0) {
@@ -27464,6 +27471,7 @@ virDomainMemorybackingFormat(virBuffer *buf,
                              const virDomainMemtune *mem)
 {
     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
+    g_auto(virBuffer) allocAttrBuf = VIR_BUFFER_INITIALIZER;
 
     if (mem->nhugepages)
         virDomainHugepagesFormat(&childBuf, mem->hugepages, mem->nhugepages);
@@ -27478,8 +27486,13 @@ virDomainMemorybackingFormat(virBuffer *buf,
         virBufferAsprintf(&childBuf, "<access mode='%s'/>\n",
                           virDomainMemoryAccessTypeToString(mem->access));
     if (mem->allocation)
-        virBufferAsprintf(&childBuf, "<allocation mode='%s'/>\n",
+        virBufferAsprintf(&allocAttrBuf, " mode='%s'",
                           virDomainMemoryAllocationTypeToString(mem->allocation));
+    if (mem->allocation_threads)
+        virBufferAsprintf(&allocAttrBuf, " threads='%u'", mem->allocation_threads);
+
+    virXMLFormatElement(&childBuf, "allocation", &allocAttrBuf, NULL);
+
     if (mem->discard)
         virBufferAddLit(&childBuf, "<discard/>\n");
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a4de46773c..48df6cc389 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2701,6 +2701,7 @@ struct _virDomainMemtune {
     int source; /* enum virDomainMemorySource */
     int access; /* enum virDomainMemoryAccess */
     int allocation; /* enum virDomainMemoryAllocation */
+    unsigned int allocation_threads;
 
     virTristateBool discard;
 };
diff --git a/tests/qemuxml2argvdata/memfd-memory-numa.xml b/tests/qemuxml2argvdata/memfd-memory-numa.xml
index 1ebcee8939..1ac87e3aef 100644
--- a/tests/qemuxml2argvdata/memfd-memory-numa.xml
+++ b/tests/qemuxml2argvdata/memfd-memory-numa.xml
@@ -10,7 +10,7 @@
     </hugepages>
     <source type='memfd'/>
     <access mode='shared'/>
-    <allocation mode='immediate'/>
+    <allocation mode='immediate' threads='8'/>
   </memoryBacking>
   <vcpu placement='static'>8</vcpu>
   <numatune>
-- 
2.34.1



More information about the libvir-list mailing list