git: 268f19aacc6a - main - vm: Reduce address space fragmentation

From: Alan Cox <alc_at_FreeBSD.org>
Date: Thu, 13 Jun 2024 20:15:12 UTC
The branch main has been updated by alc:

URL: https://cgit.FreeBSD.org/src/commit/?id=268f19aacc6af8f64c438e8515213023a2e66ed7

commit 268f19aacc6af8f64c438e8515213023a2e66ed7
Author:     Alan Cox <alc@FreeBSD.org>
AuthorDate: 2024-06-09 16:58:27 +0000
Commit:     Alan Cox <alc@FreeBSD.org>
CommitDate: 2024-06-13 20:13:45 +0000

    vm: Reduce address space fragmentation
    
    jemalloc performs two types of virtual memory allocations: (1) large
    chunks of virtual memory, where the chunk size is a multiple of a
    superpage and explicitly aligned, and (2) small allocations, mostly
    128KB, where no alignment is requested.  Typically, it starts with a
    small allocation, and over time it makes both types of allocation.
    
    With anon_loc being updated on every allocation, we wind up with a
    repeating pattern of a small allocation, a large gap, and a large,
    aligned allocation.  (As an aside, we wind up allocating a reservation
    for these small allocations, but it will never fill because the next
    large, aligned allocation updates anon_loc, leaving a gap that will
    never be filled with other small allocations.)
    
    With this change, anon_loc isn't updated on every allocation.  So, the
    small allocations will be clustered together, the large allocations will
    be clustered together, and there will be fewer gaps between the
    anonymous memory allocations.  In addition, I see a small reduction in
    reservations allocated (e.g., 1.6% during buildworld), fewer partially
    populated reservations, and a small increase in 64KB page promotions on
    arm64.
    
    Reviewed by:    kib
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D39845
---
 sys/vm/vm_map.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 3c7afcb6642f..fa71bb8a01d6 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2247,8 +2247,15 @@ again:
 		rv = vm_map_insert(map, object, offset, *addr, *addr + length,
 		    prot, max, cow);
 	}
-	if (rv == KERN_SUCCESS && update_anon)
-		map->anon_loc = *addr + length;
+
+	/*
+	 * Update the starting address for clustered anonymous memory mappings
+	 * if a starting address was not previously defined or an ASLR restart
+	 * placed an anonymous memory mapping at a lower address.
+	 */
+	if (update_anon && rv == KERN_SUCCESS && (map->anon_loc == 0 ||
+	    *addr < map->anon_loc))
+		map->anon_loc = *addr;
 done:
 	vm_map_unlock(map);
 	return (rv);
@@ -4041,9 +4048,6 @@ vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end)
 		    entry->object.vm_object != NULL)
 			pmap_map_delete(map->pmap, entry->start, entry->end);
 
-		if (entry->end == map->anon_loc)
-			map->anon_loc = entry->start;
-
 		/*
 		 * Delete the entry only after removing all pmap
 		 * entries pointing to its pages.  (Otherwise, its