xend: fix automatic vcpu NUMA placement
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 22 May 2008 14:11:06 +0000 (15:11 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 22 May 2008 14:11:06 +0000 (15:11 +0100)
The automatic NUMA placement code (find_relaxed_node) in
XendDomainInfo.py contains several bugs:
1. The domain just created shall not be considered in the load
calculation.
2. Nodes with too less memory for the domain must be considered during
the load calculation phase and abandoned later, currently these nodes
win with a load of 0.
3. CPUs which are offline shall not be considered in load calculation.
4. (Integer-)Dividing the load value by the number of cores per node
may conceal subtle load differences resulting in a non-optimal node to
be chosen.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
tools/python/xen/xend/XendDomainInfo.py

index 3f87e35693a195ba81ea264ee103055b062d0098..9381ad78c2f0821d531984d134b7ebd6acdcd594 100644 (file)
@@ -2091,28 +2091,28 @@ class XendDomainInfo:
                         xc.vcpu_setaffinity(self.domid, v, self.info['cpus'][v])
             else:
                 def find_relaxed_node(node_list):
-                    import sys 
+                    import sys
+                    nr_nodes = info['nr_nodes']
                     if node_list is None:
-                        node_list = range(0, info['nr_nodes'])
+                        node_list = range(0, nr_nodes)
                     nodeload = [0]
-                    nodeload = nodeload * info['nr_nodes']
+                    nodeload = nodeload * nr_nodes
                     from xen.xend import XendDomain
                     doms = XendDomain.instance().list('all')
-                    for dom in doms:
+                    for dom in filter (lambda d: d.domid != self.domid, doms):
                         cpuinfo = dom.getVCPUInfo()
                         for vcpu in sxp.children(cpuinfo, 'vcpu'):
-                            def vinfo(n, t):
-                                return t(sxp.child_value(vcpu, n))
-                            cpumap = vinfo('cpumap', list)
-                            for i in node_list:
+                            if sxp.child_value(vcpu, 'online') == 0: continue
+                            cpumap = list(sxp.child_value(vcpu,'cpumap'))
+                            for i in range(0, nr_nodes):
                                 node_cpumask = info['node_to_cpu'][i]
                                 for j in node_cpumask:
                                     if j in cpumap:
                                         nodeload[i] += 1
                                         break
-                    for i in node_list:
-                        if len(info['node_to_cpu'][i]) > 0:
-                            nodeload[i] = int(nodeload[i] / len(info['node_to_cpu'][i]))
+                    for i in range(0, nr_nodes):
+                        if len(info['node_to_cpu'][i]) > 0 and i in node_list:
+                            nodeload[i] = int(nodeload[i] * 16 / len(info['node_to_cpu'][i]))
                         else:
                             nodeload[i] = sys.maxint
                     index = nodeload.index( min(nodeload) )