Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 08 Mar 2017 14:27:15 -0800
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-hackers@freebsd.org
Cc:        Karl Denninger <karl@denninger.net>
Subject:   Re: Kernel UMA current occupancy statistics
Message-ID:  <2800890.fCNZHq2Y8P@ralph.baldwin.cx>
In-Reply-To: <18fdca3b-9002-db60-504b-388c628fab0e@denninger.net>
References:  <18fdca3b-9002-db60-504b-388c628fab0e@denninger.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday, August 31, 2016 08:02:06 AM Karl Denninger wrote:
> Working on the ZFS ARC code I'm trying to find documentation on the
> means by which I can determine the occupancy of a UMA slab.
> 
> There is a userland set of calls but I assume those are not the correct
> way to approach this in the kernel context.  include/sys/vm/uma.h
> declares that the returned structure is to be opaque to users of the
> facility, and the only occupancy-related function I can find is
> uma_zone_get_cur, which gives me the number of items allocated but
> uma_zone_get_max states that it will return "0" if no limit on
> allocations has been set.
> 
> Any hints on how to determine, if for example there are 50,000 "units"
> of memory that are currently held out of kmem in a given slab how many
> are actually allocated and how many are free and reusable without a
> further kernel memory allocation?
> 
> What I'm trying to determine is this (from vmstat -z):
> 
> ITEM                   SIZE  LIMIT     USED     FREE      REQ FAIL SLEEP
> zio_buf_512:            512,      0,   79865,  199359, 6495950,   0,   0
> 
> In other words how do I programmatically, inside a kernel routine (in
> this case zfs/arc.c) retrieve the "used" and "free" values if I have a
> given slab's pointer (which I can use to call kmem_cache_reap_now)?
> 
> Thanks in advance;

vmstat -z retrieves these using memstat_sysctl_uma() from libmemstat
which in turn uses the vm.zone_stats sysctl.  Looking in that function,
it seems that the used field (mt_count) is computed this way:

               mtp->mt_count = mtp->mt_numallocs - mtp->mt_numfrees;

Where numallocs and numfrees are computed by summing a set of per-CPU
stats:

                for (j = 0; j < maxcpus; j++) {
                        mtp->mt_numallocs += upsp->ups_allocs;
                        mtp->mt_numfrees += upsp->ups_frees;
                }

The free field (mt_free) is calculated similarly.  First with a global
count followed by per-CPU counts:

                mtp->mt_numfrees = uthp->uth_frees;
                for (j = 0; j < maxcpus; j++) {
                        mtp->mt_free += upsp->ups_cache_free;
                }

The vm.zone_stats sysctl is implemented by sysctl_vm_zone_stats() in
sys/vm/uma_core.c.

It seems like 'uma_zone_get_cur()' might give you USED.  You would
need to add a new function to let you calculate FREE.  You can probably
use 'uma_zone_get_cur()' as a template for implementing that other
function.  uma_zone_sumstat() might also be useful as a reference.

-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2800890.fCNZHq2Y8P>