This is a definition of waste that lets us see the differences between
alternate slab layouts. I am not sure it is the best or the most
intuitive measurement, but it at least allows for comparison. I am open
to other definitions.
Details
- Reviewers
jeff markj - Commits
- rS355708: uma: report slab efficiency
sysctl vm.uma | grep waste
Diff Detail
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
Sample output:
vali% sysctl $(sysctl -N vm.uma | grep waste) | sort -k 2 -n -r | head -n 20 vm.uma.mbuf_jumbo_9k.keg.waste: 3384 vm.uma.tfo.keg.waste: 2184 vm.uma.int_pcpu.keg.waste: 2159 vm.uma.64_pcpu.keg.waste: 2159 vm.uma.sctp_asoc.keg.waste: 1792 vm.uma.65536.keg.waste: 1720 vm.uma.VMSPACE.keg.waste: 1664 vm.uma.Mountpoints.keg.waste: 1384 vm.uma.UMA_Zones.keg.waste: 1256 vm.uma.filedesc0.keg.waste: 888 vm.uma.32768.keg.waste: 888 vm.uma.FPU_save_area.keg.waste: 872 vm.uma.THREAD.keg.waste: 680 vm.uma.NCLNODE.keg.waste: 648 vm.uma.socket.keg.waste: 584 vm.uma.sctp_raddr.keg.waste: 520 vm.uma.vmem.keg.waste: 488 vm.uma.mbuf_jumbo_16k.keg.waste: 472 vm.uma.16384.keg.waste: 472 vm.uma.g_bio.keg.waste: 440 vali% sysctl $(sysctl -N vm.uma | grep waste) | sort -k 2 -n -r | tail vm.uma.64.keg.waste: 104 vm.uma.512.keg.waste: 104 vm.uma.32_Bucket.keg.waste: 104 vm.uma.256_Bucket.keg.waste: 104 vm.uma.256.keg.waste: 104 vm.uma.2048.keg.waste: 104 vm.uma.16_Bucket.keg.waste: 104 vm.uma.128_Bucket.keg.waste: 104 vm.uma.128.keg.waste: 104 vm.uma.1024.keg.waste: 104
I see you are not counting alignment as waste, which I agree with. The comment could be better though. It took me a while to realize how that was different from rsize (again).
I would not consider the allocator's own fields waste. I would just consider the unused bit size waste for offpage. So possibly subtract the minimum size slab header that would work and add the difference between that and the offpage slab header if necessary.
I understand why you want to count the page but for people coming after you it will be a confusing definition.
I wonder if the resulting metric is the right one. Another alternative is % of an item wasted. Or % of a page. In many cases waste may be high but addressing that would require allocating quite a few contiguous pages.
Here's what it would look like without sizeof(struct vm_page):
vali% sysctl $(sysctl -N vm.uma | grep waste) | sort -k 2 -n -r | head -n 20 vm.uma.mbuf_jumbo_9k.keg.waste: 3072 vm.uma.tfo.keg.waste: 2080 vm.uma.int_pcpu.keg.waste: 2055 vm.uma.64_pcpu.keg.waste: 2055 vm.uma.sctp_asoc.keg.waste: 1688 vm.uma.VMSPACE.keg.waste: 1560 vm.uma.Mountpoints.keg.waste: 1280 vm.uma.UMA_Zones.keg.waste: 1152 vm.uma.filedesc0.keg.waste: 784 vm.uma.FPU_save_area.keg.waste: 768 vm.uma.THREAD.keg.waste: 576 vm.uma.NCLNODE.keg.waste: 544 vm.uma.socket.keg.waste: 480 vm.uma.sctp_raddr.keg.waste: 416 vm.uma.vmem.keg.waste: 384 vm.uma.g_bio.keg.waste: 336 vm.uma.AIOCB.keg.waste: 336 vm.uma.pipe.keg.waste: 296 vm.uma.sctp_ep.keg.waste: 256 vm.uma.audit_record.keg.waste: 256 vali% sysctl $(sysctl -N vm.uma | grep waste) | sort -k 2 -n -r | tail vm.uma.64.keg.waste: 0 vm.uma.512.keg.waste: 0 vm.uma.32_Bucket.keg.waste: 0 vm.uma.256_Bucket.keg.waste: 0 vm.uma.256.keg.waste: 0 vm.uma.2048.keg.waste: 0 vm.uma.16_Bucket.keg.waste: 0 vm.uma.128_Bucket.keg.waste: 0 vm.uma.128.keg.waste: 0 vm.uma.1024.keg.waste: 0
sys/vm/uma_core.c | ||
---|---|---|
4454 ↗ | (On Diff #65503) | Maybe we should not add sizeof(struct vm_page). I was worried not having it would make page-embedded slabs look better than they are, but now I think having it is confusing. |
Will rephrase.
I would not consider the allocator's own fields waste. I would just consider the unused bit size waste for offpage. So possibly subtract the minimum size slab header that would work and add the difference between that and the offpage slab header if necessary.
I think it's appropriate to count the whole offpage slab, because otherwise slabzone memory could have been put to good use. I do see how it's interesting to count the wasted slab bits specifically though (especially if one is interested in optimizing wasted bits or kegs of very small objects).
I understand why you want to count the page but for people coming after you it will be a confusing definition.
Yeah, I think I agree. I'll remove it. Justification: the vm page structures couldn't be reallocated and put to use to store client data in any case.
I wonder if the resulting metric is the right one. Another alternative is % of an item wasted. Or % of a page. In many cases waste may be high but addressing that would require allocating quite a few contiguous pages.
I think we can consider two basic parameters, _total_ space consumption by a slab, and space _available_ in the slab for allocations by clients. Let us say this might be a way to compute those:
total = keg->uk_ppera * PAGE_SIZE; if ((keg->uk_flags & UMA_ZONE_OFFPAGE) != 0) total += slab_sizeof(SLAB_MAX_SETSIZE); avail = keg->uk_ipers * roundup2(keg->uk_size, keg->uk_align + 1); if ((keg->uk_flags & UMA_ZONE_PCPU) != 0) avail *= mp_maxid + 1;
Then, what to display?
- waste: total - avail
- wastepct: 100 * (total - avail) / total
- efficiency: 100 * avail / total
- overhead: 100 * (total - avail) / avail
- inefficiency: 100 - 100 * avail / total
Out of these, I think I like "efficiency" best. I think it's easiest to understand in terms of how it scales with more items. But I think any could work. Thoughts?
Sample output:
vali% sysctl $(sysctl -N vm.uma | grep efficiency) | sort -k 2 -n | head -n 20 vm.uma.64_pcpu.keg.efficiency: 49 vm.uma.int_pcpu.keg.efficiency: 49 vm.uma.tfo.keg.efficiency: 49 vm.uma.sctp_asoc.keg.efficiency: 58 vm.uma.VMSPACE.keg.efficiency: 61 vm.uma.Mountpoints.keg.efficiency: 68 vm.uma.UMA_Zones.keg.efficiency: 71 vm.uma.mbuf_jumbo_9k.keg.efficiency: 75 vm.uma.filedesc0.keg.efficiency: 80 vm.uma.FPU_save_area.keg.efficiency: 81 vm.uma.THREAD.keg.efficiency: 85 vm.uma.NCLNODE.keg.efficiency: 86 vm.uma.socket.keg.efficiency: 88 vm.uma.sctp_raddr.keg.efficiency: 89 vm.uma.vmem.keg.efficiency: 90 vm.uma.AIOCB.keg.efficiency: 91 vm.uma.g_bio.keg.efficiency: 91 vm.uma.pipe.keg.efficiency: 92 vm.uma.UMA_Hash.keg.efficiency: 93 vm.uma.VNODE.keg.efficiency: 93 vali% sysctl $(sysctl -N vm.uma | grep efficiency) | sort -k 2 -n | tail vm.uma.mbuf.keg.efficiency: 100 vm.uma.mbuf_cluster.keg.efficiency: 100 vm.uma.mbuf_extpgs.keg.efficiency: 100 vm.uma.mbuf_packet.keg.efficiency: 100 vm.uma.nvme_request.keg.efficiency: 100 vm.uma.pf_frags.keg.efficiency: 100 vm.uma.selfd.keg.efficiency: 100 vm.uma.tfo_ccache_entries.keg.efficiency: 100 vm.uma.ttyoutq.keg.efficiency: 100 vm.uma.unpcb.keg.efficiency: 100