This change was a byproduct of the work we are doing to add NFS over RDMA (client and server) to FreeBSD.
During large NFS over RDMA reads, we found that the completion CPU can run out of page-cache bucket objects while other CPUs retain unused ones.
These allocations use M_NOVM, so UMA cannot allocate new backing pages to satisfy them. When replacement allocation fails, the fallback releases pages individually and takes the VM domain lock for each page.
This can cause a severe slowdown.
This patch reuses a full bucket when replacement allocation fails. It drains a full free bucket, or releases half the entries from a full allocation bucket. Keeping the other half avoids repeatedly draining and refilling the bucket on CPUs that also allocate.
I don't know much about UMA, to be honest, and I don't know if this is the right approach to the problem. Since it changes the allocator, it could have unintended effects elsewhere.
But anyway, the point here is that it helped in our tests and those carried out by NVIDIA. There may still be effects on other workloads that I haven't considered, as I already said. I'd appreciate your review here.
Also, one final remark: I kept bzero() for the clearing code. However, in recent reviews I've been asked to use memset() instead, so I can update that here too if needed.