Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 05 Jun 2013 05:11:20 -0700
From:      Alfred Perlstein <bright@mu.org>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        Konstantin Belousov <kostikbel@gmail.com>, svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r251282 - head/sys/kern
Message-ID:  <51AF2AE8.4080308@mu.org>
In-Reply-To: <20130604170410.M1018@besplex.bde.org>
References:  <201306030416.r534GmCA001872@svn.freebsd.org> <51AC1B49.9090001@mu.org> <20130603075539.GK3047@kib.kiev.ua> <51AC60CA.6050105@mu.org> <20130604052219.GP3047@kib.kiev.ua> <20130604170410.M1018@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help

Konstantin, is there any way to take some of Bruce's feedback into 
account to get rid of the hard coded max?

-Alfred

On 6/4/13 1:14 AM, Bruce Evans wrote:
> On Tue, 4 Jun 2013, Konstantin Belousov wrote:
>
>> On Mon, Jun 03, 2013 at 02:24:26AM -0700, Alfred Perlstein wrote:
>>> On 6/3/13 12:55 AM, Konstantin Belousov wrote:
>>>> On Sun, Jun 02, 2013 at 09:27:53PM -0700, Alfred Perlstein wrote:
>>>>> Hey Konstaintin, shouldn't this be scaled against the actual 
>>>>> amount of
>>>>> KVA we have instead of an arbitrary limit?
>>>> The commit changes the buffer cache to scale according to the 
>>>> available
>>>> KVA, making the scaling less dumb.
>>>>
>>>> I do not understand what exactly do you want to do, please describe 
>>>> the
>>>> algorithm you propose to implement instead of my change.
>>>
>>> Sure, how about deriving the hardcoded "32" from the maxkva a machine
>>> can have?
>>>
>>> Is that possible?
>> I do not see why this would be useful. Initially I thought about simply
>> capping nbuf at 100000 without referencing any "memory". Then I realized
>> that this would somewhat conflict with (unlikely) changes to the value
>> of BKVASIZE due to "factor".
>
> The presence of BKVASIZE in 'factor' is a bug.  My version never had this
> bug (see below for a patch).  The scaling should be to maximize nbuf,
> subject to non-arbitrary limits on physical memory and kva, and now an
> arbirary limit of about 100000 / (BKVASIZE / 16384) on nbuf.  Your new
> limit is arbitrary so it shouldn't affect nbuf depending on BKVASIZE.
>
> Expanding BKVASIZE should expand kva use, but on i386 this will soon
> hit a non-arbitary kva limit so nbuf will not be as high as preferred.
> nbuf needs to be very large mainly to support file systems with small
> buffers.  Even 100000 only gives 50MB of buffering if the fs block
> size is 512.  This would shrink to only 12.5MB if BKVASIZE is expanded
> by a factor of 4 and the bug is not fixed.  If 25000 buffers after
> expanding BKVASIZE is enough, then that should be the arbitary limit
> (independent of BKVASIZE) so as to save physical memory.
>
> On i386 systems with 1GB RAM, nbuf defaults to about 7000.  With an
> fs block size of 512, that can buffer 3.5MB.  Expanding BKVASIZE by a
> factor of 4 shrinks this to 0.875MB in -current.  That is ridiculously
> small.  VMIO limits the lossage from this.
>
> BKVASIZE was originally 8KB.  I forget if nbuf was halved by not 
> modifying
> the scale factor when it was expanded to 16KB.  Probably not.  I used to
> modify the scale factor to get twice as many as the default nbuf, but
> once the default nbuf expanded to a few thousand it became large enough
> for most purposes so I no longer do this.
>
> Except on arches with extremely limit kva like i386, KVASIZE should be
> MAXBSIZE, and all of the complications for expanding a buffer's kva
> beyond BKVASIZE and handling the fragmentation problems caused by this
> shouldn't exist.  Limits like vfs.maxbufspace should be scaled by
> NOMBSIZE = current BKVASIZE instead of BKVASIZE.  Oops, my NOMBSIZE
> has similar logical problems to BKVASIZE.  It needs to be precisely
> 16KB to preserve the defaults for nbuf and maxbufspace, but the nominal
> (ffs) buffer size is now 32KB.  So the heuristic scale factors should
> use the historical magic number 16K.  I changed sequential_heuristic()
> to use a hard-coded 16K instead of BKVASIZE.  The correct number here
> depends on disk technology.
>
> The patch has many style fixes:
>
> @ Index: vfs_bio.c
> @ ===================================================================
> @ RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v
> @ retrieving revision 1.436
> @ diff -u -2 -r1.436 vfs_bio.c
> @ --- vfs_bio.c    17 Jun 2004 17:16:49 -0000    1.436
> @ +++ vfs_bio.c    3 Jun 2013 16:04:34 -0000
> @ @@ -419,64 +493,54 @@
> @ @  /*
> @ - * Calculating buffer cache scaling values and reserve space for 
> buffer
> @ + * Calculate buffer cache scaling values and reserve space for buffer
> @   * headers.  This is called during low level kernel initialization and
> @   * may be called more then once.  We CANNOT write to the memory area
> @   * being reserved at this time.
> @   */
> @ -caddr_t
> @ -kern_vfs_bio_buffer_alloc(caddr_t v, long physmem_est)
> @ +void *
> @ +vfs_bio_alloc(void *va)
>
> The API name was verbose and bogus.  The prefix for this subsystem is
> vfs_bio_, not kern_vfs_bio_.  This is a generic allocation routine.
> It always allocated swbufs and has expanded to do more allocations.
>
> @  {
> @ -    /*
> @ -     * physmem_est is in pages.  Convert it to kilobytes (assumes
> @ -     * PAGE_SIZE is >= 1K)
> @ -     */
> @ -    physmem_est = physmem_est * (PAGE_SIZE / 1024);
>
> I use the global physmem.  This change may be too i386-specific. In
> with 8-16 RAM, a significant amount of RAM may be eaten by the kernel
> image or perhaps just unavailable to the kernel.  Now memories are
> larger and the amount eaten is relatively insignificant (since we are
> only using a small fraction of physmem, only the relative error matters).
>
> @ +    int factor, memsize;
> @ @      /*
> @ -     * The nominal buffer size (and minimum KVA allocation) is 
> BKVASIZE.
> @ -     * For the first 64MB of ram nominally allocate sufficient 
> buffers to
> @ -     * cover 1/4 of our ram.  Beyond the first 64MB allocate 
> additional
> @ -     * buffers to cover 1/20 of our ram over 64MB.  When auto-sizing
> @ -     * the buffer cache we limit the eventual kva reservation to
> @ +     * The nominal buffer size is NOMBSIZE.
> @ +     * For the first 4MB of RAM, allocate 50 buffers.
> @ +     * For the next 60MB of RAM, nominally allocate sufficient 
> buffers to
> @ +     * cover 1/4 of the RAM.  Beyond the first 64MB allocate 
> additional
> @ +     * buffers to cover 1/20 of the RAM.  When auto-sizing
> @ +     * the buffer cache, limit the eventual kva reservation to
> @       * maxbcache bytes.
>
> Fix old bitrot in this comment, and update for my changes.
> - the first 4MB wasn't mentioned
> - the minimum clamp wasn't mentioned
> - replace BKVASIZE by NOMBSIZE so that I can change BKVASIZE without
>   changing the default nbuf (subject to maxbcache).
>
> The bitrot of the magic number 1/20 is not fixed.  The code uses 1/10.
> This is fixed in -current.  I should have noticed this before, since
> I used to have to change the code to get 1/10 instead of 1/20.
>
> I hope you updated the comment for recent changes, but I don't like
> having magic numbers in comments.
>
> @       *
> @ -     * factor represents the 1/4 x ram conversion.
> @ +     * `factor' represents the 1/4 of RAM conversion.
> @       */
> @ +#define    NOMBSIZE    imax(PAGE_SIZE, 16384)    /* XXX */
> @      if (nbuf == 0) {
> @ -        int factor = 4 * BKVASIZE / 1024;
> @ +        /*
> @ +         * physmem is in pages.  Convert it to a size in kilobytes.
> @ +         * XXX no ptob().
> @ +         */
> @ +        memsize = ctob(physmem) / 1024;
> @ @ +        factor = 4 * NOMBSIZE / 1024;
> @          nbuf = 50;
> @ -        if (physmem_est > 4096)
> @ -            nbuf += min((physmem_est - 4096) / factor,
> @ -                65536 / factor);
> @ -        if (physmem_est > 65536)
> @ -            nbuf += (physmem_est - 65536) * 2 / (factor * 5);
> @ -
> @ -        if (maxbcache && nbuf > maxbcache / BKVASIZE)
> @ -            nbuf = maxbcache / BKVASIZE;
>
> The maxbcache limit must be applied to the non-default nbuf too.
>
> @ +        if (memsize > 4096)
> @ +            nbuf += imin((memsize - 4096) / factor,
> @ +                (65536 - 4096) / factor);
> @ +        if (memsize > 65536)
> @ +            nbuf += (memsize - 65536) * 2 / (factor * 5);
> @      }
> @ -
> @ -#if 0
> @ -    /*
> @ -     * Do not allow the buffer_map to be more then 1/2 the size of the
> @ -     * kernel_map.
> @ -     */
> @ -    if (nbuf > (kernel_map->max_offset - kernel_map->min_offset) / 
> @ -        (BKVASIZE * 2)) {
> @ -        nbuf = (kernel_map->max_offset - kernel_map->min_offset) / 
> @ -            (BKVASIZE * 2);
> @ -        printf("Warning: nbufs capped at %d\n", nbuf);
> @ -    }
> @ -#endif
>
> Already removed in -current.
>
> @ +    if (nbuf > maxbcache / BKVASIZE)
> @ +        nbuf = maxbcache / BKVASIZE;
> @ @      /*
> @       * swbufs are used as temporary holders for I/O, such as paging 
> I/O.
> @ -     * We have no less then 16 and no more then 256.
> @ +     * There must be between 16 and 256 of them.
> @       */
> @ -    nswbuf = max(min(nbuf/4, 256), 16);
> @ +    nswbuf = imax(imin(nbuf / 4, 256), 16);
> @  #ifdef NSWBUF_MIN
> @      if (nswbuf < NSWBUF_MIN)
> @          nswbuf = NSWBUF_MIN;
> @  #endif
> @ +
> @  #ifdef DIRECTIO
> @      ffs_rawread_setup();
> @ @@ -484,12 +548,12 @@
> @ @      /*
> @ -     * Reserve space for the buffer cache buffers
> @ +     * Reserve space for swbuf headers and buffer cache buffers.
> @       */
> @ -    swbuf = (void *)v;
> @ -    v = (caddr_t)(swbuf + nswbuf);
> @ -    buf = (void *)v;
> @ -    v = (caddr_t)(buf + nbuf);
> @ +    swbuf = va;
> @ +    va = swbuf + nswbuf;
> @ +    buf = va;
> @ +    va = buf + nbuf;
> @ @ -    return(v);
> @ +    return (va);
> @  }
> @
>
> Don't use the caddr_t mistake.  The API was also changed to not use it.
>
> Bruce
>




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