Page MenuHomeFreeBSD

vm_reserv: add reservation-aware UMA small_alloc
AcceptedPublic

Authored by bnovkov on May 1 2024, 1:54 PM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, Jun 13, 6:29 PM
Unknown Object (File)
Sun, Jun 2, 5:21 PM
Unknown Object (File)
Mon, May 27, 2:14 AM
Unknown Object (File)
May 13 2024, 7:10 AM
Unknown Object (File)
May 10 2024, 3:49 AM
Unknown Object (File)
May 8 2024, 11:07 PM
Unknown Object (File)
May 6 2024, 12:54 AM
Unknown Object (File)
May 5 2024, 3:48 AM
Subscribers

Details

Reviewers
kib
markj
alc
Summary

This patch adds a reservation-aware replacement for uma_small_alloc.

The vm_reserv_uma_small_{alloc, free} routines use unmanaged reservations to allocate 0-order pages for UMA zones.
Those reservations are placed in dedicated, per-domain UMA small_alloc queues that keep track of partially populated reservations and reservations used for NOFREE allocations.

The allocator falls back to vm_page_alloc_noobj_domain in case of memory pressure.

Test Plan

All changes in this patch series were tested on amd64 using a bhyve vm.
No errors or panics were encountered while running vm-related stress2 tests for several hours.

I can confirm that everything builds properly for all other architectures.
I'm currently in the process of running smoke tests for other architectures and will update the revision if anything pops up.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

Removed stray UMA code from diff.

sys/vm/vm_reserv.c
1762

vm_reserv_free_page_noobj() is used before declared (at least when D45043 is applied too).

Update vm_reserv_uma_small_alloc to retry if someone else filled up a partial reservation.

I spent some time evaluating this patch with four different metrics (thanks @markj for the first two):

  • Number of reservations with at least one NOFREE page
  • Number of reservations with at least one UMA slab, excluding NOFREE slabs
  • vm.pde.promotions
  • vm.pde.mappings

The first two metrics track how scattered these pages types are in memory. I've gathered them by iterating through all UMA zones and their slab lists.

I ran buildkernel four times in a row on a 10GB bhyve VM, and sampled the metrics before each run.

Results without patches:

no. NOFREEno. SLABvm.pde.promotionsvm.pde.mappings
4273720
46914421384914089
47614912738428317
48515304077942534

Results with patches:

no. NOFREEno. SLABvm.pde.promotionsvm.pde.mappings
1367711
2214411406614147
2214632780328456
2214684146042752

The amount reservations "tainted" by NOFREE pages is drastically smaller with this patch. It also remains stable throughout the test, whereas the non-patched version grows steadily.
This also seems to hold true for the second column which grows a lot less for the patched version, indicating that we are packing slab pages more efficiently.
The values for vm.pde.promotions and vm.pde.mappings are also slightly larger when compared to the unpatched version, although I'll re-evaluate this a couple more times to make sure.

I spent some time evaluating this patch with four different metrics (thanks @markj for the first two):

  • Number of reservations with at least one NOFREE page
  • Number of reservations with at least one UMA slab, excluding NOFREE slabs
  • vm.pde.promotions
  • vm.pde.mappings

Addendum - @netchild has been running -CURRENT with this patch series for some time with no issues encountered so far.
@netchild please correct me if I've misunderstood something, but the machine in question is a laptop with 8GB of RAM and it is primarily used to run various jailed services (~30 jails) and build packages.

I'd really love to get some feedback about the patch since it went through a couple of rounds of testing and appears to be both stable and effective at containing NOFREE and regular slabs.

Addendum - @netchild has been running -CURRENT with this patch series for some time with no issues encountered so far.
@netchild please correct me if I've misunderstood something, but the machine in question is a laptop with 8GB of RAM and it is primarily used to run various jailed services (~30 jails) and build packages.

Dual socket, 24 CPU (incl. HT), (old) Xeon server. 72 GB RAM. About 30 jails (not counting the poudriere jails). Various services, mysql, postgresql, redis, dns, ldap, various instances of php and nginx, various java services, ...

I haven't updated yet to the most recent update of this patch.

I've seen a lot of instabilities in other places (fixed based upon my reports), but the current BE I have is rock solid with this change (plus D45043 and D45045).

sys/vm/vm_reserv.c
223
225

May be move the sentence about 'two reservation queues' before listing them.

1459

We try to keep lock names under 6 symbols (for top).

1637

rv initialization seems to be not needed

1643

Why not just 'return (rv);'? The found label is not used for anything else.

1723

Does it make sense to move this code (starting from the 'Initialize page' comment) into a helper, placed and also used in vm_page.c?

bnovkov added inline comments.
sys/vm/vm_reserv.c
1643

You're right, that makes more sense.

1723

Well, I think it does and I have contemplated about doing so but ultimately gave up because I didn't want to drag out the patches too much.
But I agree that this is something worth doing, I'll try to land this in a separate revision.

kib added inline comments.
sys/vm/vm_reserv.c
1643
This revision is now accepted and ready to land.Sun, Jun 16, 8:39 PM