> Date: Wed, 17 Jun 2015 09:19:57 +0000
> From: Visa Hankala <[email protected]>
>
> On Tue, Jun 16, 2015 at 23:57 +0200, Mark Kettenis wrote:
> > You're definitely on to something. It certainly looks like your diff
> > fixes the bug. However, if there is no constraint, it would make
> > sense to pick a page from the size tree of the right type. Not sure
> > if that optimization would really matter though.
>
> How about the following patch? It adds an opportunistic size tree check
> before the address tree search. If there are no constraints, the
> opportunistically checked entry will be selected directly.
>
> The updated patch does not seem to have any clear impact on
> performance, at least when there is no heavy memory contention. In my
> cursory tests, kernel build times were effectively the same on an amd64
> with and without the fix. The octeon fared similarly.
Thanks. Even if there is no performance benefit, reducing
fragmentation helps.
Committed. Thanks again for figuring this out.
> Index: uvm/uvm_pmemrange.c
> ===================================================================
> RCS file: src/sys/uvm/uvm_pmemrange.c,v
> retrieving revision 1.44
> diff -u -p -r1.44 uvm_pmemrange.c
> --- uvm/uvm_pmemrange.c 13 Nov 2014 00:47:44 -0000 1.44
> +++ uvm/uvm_pmemrange.c 17 Jun 2015 07:12:14 -0000
> @@ -1708,11 +1708,35 @@ uvm_pmr_get1page(psize_t count, int memt
> found = TAILQ_NEXT(found, pageq);
>
> if (found == NULL) {
> - found = RB_ROOT(&pmr->size[memtype]);
> - /* Size tree gives pg[1] instead of pg[0] */
> + /*
> + * Check if the size tree contains a range
> + * that intersects with the boundaries. As the
> + * allocation is for any page, try the smallest
> + * range so that large ranges are preserved for
> + * more constrained cases. Only one entry is
> + * checked here, to avoid a brute-force search.
> + *
> + * Note that a size tree gives pg[1] instead of
> + * pg[0].
> + */
> + found = RB_MIN(uvm_pmr_size,
> + &pmr->size[memtype]);
> if (found != NULL) {
> found--;
> -
> + if (!PMR_INTERSECTS_WITH(
> + atop(VM_PAGE_TO_PHYS(found)),
> + atop(VM_PAGE_TO_PHYS(found)) +
> + found->fpgsz, start, end))
> + found = NULL;
> + }
> + }
> + if (found == NULL) {
> + /*
> + * Try address-guided search to meet the page
> + * number constraints.
> + */
> + found = RB_ROOT(&pmr->addr);
> + if (found != NULL) {
> found = uvm_pmr_rootupdate(pmr, found,
> start, end, memtype);
> }
>