Automatic NUMA placement for xl
PATCH 1/1 Automatic NUMA placement for xl
Hello again,
This is a new version (fixing a small bug) of this series:
<patchbomb.1341932613@Solace>, which in turn was a repost of what remained un-committed of my NUMA placement series.
As already stated, the splat on 1-node-only systems has been resolved as per Ian Campbell's suggestion (thanks!), and that was the only thing I'm aware that was preventing from checking-in these last patches. While at it, I also addressed all any other observation made during review, namely, typos and rewording of some sentences, as well as an improved filtering solution for avoiding generating a lot of potential duplicate placement candidates when cpupool are being used.
All the patches have already been acked, although with some minor nits that should be gone now.
If you have any further comment, I'm here to answer. :-)
Thanks and Regards,
Dario
PATCH 1/1 If a domain does not have a VCPU affinity, try to pin it automatically to some
PCPUs. This is done taking into account the NUMA characteristics of the host. In fact, we look for a combination of host's NUMA nodes with enough free memory and number of PCPUs for the new domain, and pin it to the VCPUs of those nodes.
Once we know which ones, among all the possible combinations, represents valid placement candidates for a domain, use some heuistics for deciding which is the best. For instance, smaller candidates are considered to be better, both from the domain's point of view (fewer memory spreading among nodes) and from the system as a whole point of view (fewer memoy fragmentation). In case of candidates of equal sizes (i.e., with the same number of nodes), the amount of free memory and the number of domain already assigned to their nodes are considered. Very often, candidates with greater amount of memory are the one we wants, as this is also good for keeping memory fragmentation under control. However, if the difference in how much free memory two candidates have, the number of assigned domains might be what decides which candidate wins.
This all happens internally to libxl, and no API for driving the mechanism is provided for now. This matches what xend already does.
---
Changes from v3:
* fixed a double free on non-NUMA systems (namely, when just 1 node exists).
* Reword an ambiguous sentence in xl's man page, as requested during review.
* Do no special case single node systems in libxl__get_numa_candidates(), to avoid generating a spurious warning on them.
Changes from v2:
* lots of typos.
* Clayfied some comments, as requested during (ijc's) review.
* Added some more information/reference for the combination generation algorithm.
* nodemap_to_nodes_cpus() function renamed to nodemap_to_nr_cpus().
* libxl_bitmap_init() used to make sure we do not try to free random memory on failure paths of functions that allocates a libxl_bitmap.
* Always invoke libxl__sort_numa_candidates(), even if we get there with just 1 candidate, as requested during review.
* Simplified the if-s that check for input parameter consistency in libxl__get_numa_candidates() as requested during (gwd's) review.
* Comparison function for candidates changed so that it now provides total ordering, as requested during review. It is still using FP arithmetic, though. Also I think that just putting the difference between the amount of free memory and between the number of assigned domains of two candidates in a single formula (after normalizing and weighting them) is both clear and effective enough.
* Function definitions moved to a numa specific source file (libxl_numa.c), as suggested during review.
Changes from v1:
* This patches incorporates the changes from both "libxl, xl: enable automatic placement of guests on NUMA nodes" and "libxl, xl: heuristics for reordering NUMA placement candidates" from v1.
* The logic of the algorithm is basically the same as in v1, but the splitting of it in the various functions has been completely redesigned from scratch.
* No public API for placement or candidate generation is now exposed, everything happens within libxl, as agreed during v1 review.
* The relevant documentation have been moved near the actual functions and features. Also, the amount and (hopefully!) the quality of the documentation has been improved a lot, as requested.
* All the comments about using the proper libxl facilities and helpers for allocations, etc., have been considered and applied.
* This patch still bails out from NUMA optimizations if it find out cpupools are being utilized. It is next patch that makes the two things interact properly, as suggested during review.
docs/man/xl.cfg.pod.5 +8 -2
@@ -111,8 +111,8 @@ created online and the remainder will be =item B<cpus="CPU-LIST"> -List of which cpus the guest is allowed to use. Default behavior is -`all cpus`. A C<CPU-LIST> may be specified as follows: +List of which cpus the guest is allowed to use. By default xl will (via +libxl) pick some cpus (see below). A C<CPU-LIST> may be specified as follows: =over 4
@@ -132,6 +132,12 @@ run on cpu #3 of the host. =back +If this option is not specified, libxl automatically tries to place the new +domain on the host's NUMA nodes (provided the host has more than one NUMA +node) by pinning it to the cpus of those nodes. A heuristic approach is +utilized with the goals of maximizing performance for the domain and, at +the same time, achieving efficient utilization of the host's CPUs and RAM. + =item B<cpu_weight=WEIGHT> A domain with a weight of 512 will get twice as much CPU as a domain
tools/libxl/Makefile +1 -1
@@ -66,7 +66,7 @@ LIBXL_LIBS += -lyajl -lm LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \ libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o \ libxl_internal.o libxl_utils.o libxl_uuid.o \ - libxl_json.o libxl_aoutils.o \ + libxl_json.o libxl_aoutils.o libxl_numa.o \ libxl_save_callout.o _libxl_save_msgs_callout.o \ libxl_qmp.o libxl_event.o libxl_fork.o $(LIBXL_OBJS-y) LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
tools/libxl/libxl_dom.c +115 -0
128 lines not on this page · raw message
tools/libxl/libxl_internal.h +134 -0
140 lines not on this page · raw message
tools/libxl/libxl_numa.c new file +377 -0
377 lines not on this page · raw message
PATCH 1/1 In such a way that only the cpus belonging to the cpupool of the
In reply to Dario Faggiolidomain being placed are considered for the placement itself.
This happens by filtering out all the nodes in which the cpupool has not any cpu from the placement candidates. After that -- as a cpu pooling not necessarily happens at NUMA nodes boundaries -- we also make sure only the actual cpus that are part of the pool are considered when counting how much processors a placement candidate provides.
---
Changes from v4:
* fixed a bug in the cpupool filtering logic (also the number of nodes should be affected by that)
Changes from v3:
* fixed a double free on non-NUMA systems (namely, when just 1 node exists).
* Changed the filtering logic: now only the meaningful combinations and nodemap are being considered.
Changes from v2:
* fixed typos in comments.
tools/libxl/libxl_dom.c +26 -14
@@ -132,25 +132,29 @@ static int numa_cmpf(const void *v1, con }/* The actual automatic NUMA placement routine */ -static int numa_place_domain (libxl__gc *gc,libxl_domain_build_info *info) +static int numa_place_domain (libxl__gc *gc,uint32_t domid, +libxl_domain_build_info *info) {int nr_candidates =0 ;libxl__numa_candidate *candidates =NULL ;libxl_bitmap candidate_nodemap; -libxl_cpupoolinfo *pinfo; -int nr_pools, rc =0 ; +libxl_cpupoolinfo cpupool_info; +int i, cpupool, rc =0 ;uint32_t memkb;libxl_bitmap_init (&candidate_nodemap); -/* First of all, if cpupools are in use, better not to mess with them */ - pinfo =libxl_list_cpupool (CTX , &nr_pools); -if (!pinfo) -return ERROR_FAIL ; -if (nr_pools >1 ) { -LOG (NOTICE ,"skipping NUMA placement as cpupools are in use" ); - goto out; - } +/* +* Extract the cpumap from the cpupool the domain belong to. In fact, +* it only makes sense to consider the cpus/nodes that are in there +* for placement. +*/ + rc = cpupool =libxl__domain_cpupool (gc, domid); +if (rc <0 ) +return rc; + rc =libxl_cpupool_info (CTX , &cpupool_info, cpupool); +if (rc) +return rc; rc =libxl_domain_need_memory (CTX , info, &memkb);if (rc)
@@ -162,7 +166,8 @@ static int numa_place_domain(libxl__gc */* Find all the candidates with enough free memory and at least * as much pcpus as the domain has vcpus. */ - rc =libxl__get_numa_candidates (gc, memkb, info->max_vcpus,0 ,0 , + rc =libxl__get_numa_candidates (gc, memkb, info->max_vcpus, +0 ,0 , &cpupool_info.cpumap, &candidates, &nr_candidates);if (rc) goto out;
@@ -188,13 +193,20 @@ static int numa_place_domain(libxl__gc *if (rc) goto out; +/* Avoid trying to set the affinity to cpus that might be in the +* nodemap but not in our cpupool. */ +libxl_for_each_set_bit (i, info->cpumap) { +if (!libxl_bitmap_test (&cpupool_info.cpumap, i)) +libxl_bitmap_reset (&info->cpumap, i); + } +LOG (DETAIL ,"NUMA placement candidate with %d nodes, %d cpus and " "%" PRIu32" KB free selected" , candidates[0 ].nr_nodes, candidates[0 ].nr_cpus, candidates[0 ].free_memkb /1024 ); out:libxl_bitmap_dispose (&candidate_nodemap); -libxl_cpupoolinfo_list_free (pinfo, nr_pools); +libxl_cpupoolinfo_dispose (&cpupool_info);return rc; }
@@ -217,7 +229,7 @@ int libxl__build_pre(libxl__gc *gc, uint* whatever that turns out to be. */ if (libxl_bitmap_is_full (&info->cpumap)) { -int rc =numa_place_domain (gc, info); +int rc =numa_place_domain (gc, domid, info);if (rc)return rc; }
tools/libxl/libxl_internal.h +7 -4
@@ -2289,14 +2289,17 @@ typedef struct {* least that amount of free memory and that number of cpus, respectively. If * min_free_memkb and/or min_cpus are 0, the candidates' free memory and number * of cpus won't be checked at all, which means a candidate will always be -* considered suitable wrt the specific constraint. cndts is where the list of -* exactly nr_cndts candidates is returned. Note that, in case no candidates -* are found at all, the function returns successfully, but with nr_cndts equal -* to zero. +* considered suitable wrt the specific constraint. suitable_cpumap is useful +* for specifying we want only the cpus in that mask to be considered while +* generating placement candidates (for example because of cpupools). cndts is +* where the list of exactly nr_cndts candidates is returned. Note that, in +* case no candidates are found at all, the function returns successfully, but +* with nr_cndts equal to zero. */ _hidden int libxl__get_numa_candidates(libxl__gc *gc,uint32_t min_free_memkb,int min_cpus,int min_nodes,int max_nodes, +const libxl_bitmap *suitable_cpumap,libxl__numa_candidate *cndts[],int *nr_cndts);/* Initialization, allocation and deallocation for placement candidates */
tools/libxl/libxl_numa.c +65 -25
177 lines not on this page · raw message
PATCH 1/1 About rationale, usage and (some small bits of) API
In reply to Dario Faggioli---
Changes from v3:
* typos and rewording of some sentences, as suggested during review.
Changes from v1:
* API documentation moved close to the actual functions.
docs/misc/xl-numa-placement.markdown new file +89 -0
@@ -0,0 +1,89 @@ +# Guest Automatic NUMA Placement in libxl and xl # + +## Rationale ## + +NUMA means the memory accessing times of a program running on a CPU depends on +the relative distance between that CPU and that memory. In fact, most of the +NUMA systems are built in such a way that each processor has its local memory, +on which it can operate very fast. On the other hand, getting and storing data +from and on remote memory (that is, memory local to some other processor) is +quite more complex and slow. On these machines, a NUMA node is usually defined +as a set of processor cores (typically a physical CPU package) and the memory +directly attached to the set of cores. + +The Xen hypervisor deals with Non-Uniform Memory Access (NUMA]) machines by +assigning to its domain a "node affinity", i.e., a set of NUMA nodes of the +host from which it gets its memory allocated. + +NUMA awareness becomes very important as soon as many domains start running +memory-intensive workloads on a shared host. In fact, the cost of accessing non +node-local memory locations is very high, and the performance degradation is +likely to be noticeable. + +## Guest Placement in xl ## + +If using xl for creating and managing guests, it is very easy to ask for both +manual or automatic placement of them across the host's NUMA nodes. + +Note that xm/xend does the very same thing, the only differences residing in +the details of the heuristics adopted for the placement (see below). + +### Manual Guest Placement with xl ### + +Thanks to the "cpus=" option, it is possible to specify where a domain should +be created and scheduled on, directly in its config file. This affects NUMA +placement and memory accesses as the hypervisor constructs the node affinity of +a VM basing right on its CPU affinity when it is created. + +This is very simple and effective, but requires the user/system administrator +to explicitly specify affinities for each and every domain, or Xen won't be +able to guarantee the locality for their memory accesses. + +It is also possible to deal with NUMA by partitioning the system using cpupools +(available in the upcoming release of Xen, 4.2). Again, this could be "The +Right Answer" for many needs and occasions, but has to to be carefully +considered and manually setup by hand. + +### Automatic Guest Placement with xl ### + +If no "cpus=" option is specified in the config file, libxl tries to figure out +on its own on which node(s) the domain could fit best. It is worthwhile noting +that optimally fitting a set of VMs on the NUMA nodes of an host is an +incarnation of the Bin Packing Problem. In fact, the various VMs with different +memory sizes are the items to be packed, and the host nodes are the bins. That +is known to be NP-hard, thus. We will therefore be using some heuristics. + +The first thing to do is finding a node, or even a set of nodes, that have +enough free memory and enough physical CPUs for accommodating the one new +domain. The idea is to find a spot for the domain with at least as much free +memory as it has configured, and as much pCPUs as it has vCPUs. After that, +the actual decision on which solution to go for happens accordingly to the +following heuristics: + + * candidates involving fewer nodes come first. In case two (or more) + candidates span the same number of nodes, + * the amount of free memory and the number of domains assigned to the + candidates are considered. In doing that, candidates with greater amount + of free memory and fewer assigned domains are preferred, with free memory + "weighting" three times as much as number of domains. + +Giving preference to candidates with fewer nodes ensures better performance for +the guest, as it avoid spreading its memory among different nodes. Favouring +the nodes that have the largest amounts of free memory helps keeping the memory +fragmentation small, from a system wide perspective. However, if more +candidates fulfil these criteria by roughly the same extent, having the number +of domains the candidates are "hosting" helps balancing the load on the various +nodes. + +## Guest Placement within libxl ## + +xl achieves automatic NUMA just because libxl does it interrnally. +No API is provided (yet) for interacting with this feature and modify +the library behaviour regarding automatic placement, it just happens +by default if no affinity is specified (as it is with xm/xend). + +For actually looking and maybe tweaking the mechanism and the algorithms it +uses, all is implemented as a set of libxl internal interfaces and facilities. +Look at the comment "Automatic NUMA placement" in libxl\_internal.h. + +Note this may change in future versions of Xen/libxl.
Quoted 2 lines · Dario Faggioli
Hello again,
Gah #@$%! For some reason I don't really understand, subject lines are messy in this posting. I gave it another try, if applying, that would produce better changelogs (<patchbomb.1342458791@Solace>).
Sorry for the overhead caused :-(
Dario
Signature · 4 lines
<<This happens because I choose it to happen!>> (Raistlin Majere) ----------------------------------------------------------------- Dario Faggioli, Ph.D, http://retis.sssup.it/people/faggioli Senior Software Engineer, Citrix Systems R&D Ltd., Cambridge (UK)
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xen.org/xen-devel