auto-tune mfs cache size based on FS usage and remaining system memory

This commit is contained in:
Ben Gras 2011-02-28 14:19:19 +00:00
parent b6f25271a9
commit c90cdadcfb
6 changed files with 106 additions and 11 deletions

View file

@ -1100,7 +1100,7 @@
/* Basic vm calls allowed to every process. */
#define VM_BASIC_CALLS \
VM_MMAP, VM_MUNMAP, VM_MUNMAP_TEXT, VM_MAP_PHYS, VM_UNMAP_PHYS, \
VM_FORGETBLOCKS, VM_FORGETBLOCK, VM_YIELDBLOCKGETBLOCK
VM_FORGETBLOCKS, VM_FORGETBLOCK, VM_YIELDBLOCKGETBLOCK, VM_INFO
/*===========================================================================*
* Messages for IPC server *

View file

@ -16,8 +16,10 @@
#include "fs.h"
#include <minix/u64.h>
#include <sys/param.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include "buf.h"
#include "super.h"
#include "inode.h"
@ -538,14 +540,17 @@ struct buf *bp;
}
/*===========================================================================*
* set_blocksize *
* cache_resize *
*===========================================================================*/
PUBLIC void set_blocksize(unsigned int blocksize)
PRIVATE void cache_resize(unsigned int blocksize, unsigned int bufs)
{
struct buf *bp;
struct inode *rip;
int scale, r;
ASSERT(blocksize > 0);
#define MINBUFS 10
assert(blocksize > 0);
assert(bufs >= MINBUFS);
for (bp = &buf[0]; bp < &buf[nr_bufs]; bp++)
if(bp->b_count != 0) panic("change blocksize with buffer in use");
@ -553,10 +558,76 @@ PUBLIC void set_blocksize(unsigned int blocksize)
for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
if (rip->i_count > 0) panic("change blocksize with inode in use");
buf_pool(nr_bufs);
buf_pool(bufs);
fs_block_size = blocksize;
}
/*===========================================================================*
* bufs_heuristic *
*===========================================================================*/
PRIVATE int bufs_heuristic(struct super_block *sp)
{
struct vm_stats_info vsi;
int r, bufs;
u32_t btotal, bfree, bused, kbytes_used_fs,
kbytes_total_fs, kbcache, kb_fsmax;
u32_t kbytes_remain_mem;
/* but we simply need MINBUFS no matter what, and we don't
* want more than that if we're a memory device
*/
if(major(sp->s_dev) == MEMORY_MAJOR) {
bufs = MINBUFS;
return bufs;
}
/* set a reasonable cache size; cache at most a certain
* portion of the used FS, and at most a certain %age of remaining
* memory
*/
if((vm_info_stats(&vsi) != OK)) {
bufs = 1024;
printf("mfs: heuristic info fail: default to %d bufs\n", bufs);
return bufs;
}
kbytes_remain_mem = div64u(mul64u(vsi.vsi_free, vsi.vsi_pagesize), 1024);
/* check fs usage. */
blockstats(&btotal, &bfree, &bused);
kbytes_used_fs = div64u(mul64u(bused, sp->s_block_size), 1024);
kbytes_total_fs = div64u(mul64u(btotal, sp->s_block_size), 1024);
/* heuristic for a desired cache size based on FS usage;
* but never bigger than half of the total filesystem
*/
kb_fsmax = sqrt(kbytes_used_fs)*40;
kb_fsmax = MIN(kb_fsmax, kbytes_total_fs/2);
/* heuristic for a maximum usage - 10% of remaining memory */
kbcache = MIN(kbytes_remain_mem/10, kb_fsmax);
bufs = kbcache * 1024 / sp->s_block_size;
/* but we simply need MINBUFS no matter what */
if(bufs < MINBUFS)
bufs = MINBUFS;
return bufs;
}
/*===========================================================================*
* set_blocksize *
*===========================================================================*/
PUBLIC void set_blocksize(struct super_block *sp)
{
int bufs;
cache_resize(sp->s_block_size, MINBUFS);
bufs = bufs_heuristic(sp);
cache_resize(sp->s_block_size, bufs);
}
/*===========================================================================*
* buf_pool *
*===========================================================================*/
@ -565,7 +636,7 @@ PUBLIC void buf_pool(int new_nr_bufs)
/* Initialize the buffer pool. */
register struct buf *bp;
assert(new_nr_bufs > 0);
assert(new_nr_bufs >= MINBUFS);
if(nr_bufs > 0) {
assert(buf);

View file

@ -68,7 +68,7 @@ PUBLIC int fs_readsuper()
return(r);
}
set_blocksize(superblock.s_block_size);
set_blocksize(&superblock);
/* Get the root inode of the mounted file system. */
if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL) {

View file

@ -18,7 +18,7 @@ _PROTOTYPE( void free_zone, (dev_t dev, zone_t numb) );
_PROTOTYPE( struct buf *get_block, (dev_t dev, block_t block,int only_search));
_PROTOTYPE( void invalidate, (dev_t device) );
_PROTOTYPE( void put_block, (struct buf *bp, int block_type) );
_PROTOTYPE( void set_blocksize, (unsigned int blocksize) );
_PROTOTYPE( void set_blocksize, (struct super_block *) );
_PROTOTYPE( void rw_scattered, (dev_t dev,
struct buf **bufq, int bufqsize, int rw_flag) );
@ -103,6 +103,7 @@ _PROTOTYPE( int read_super, (struct super_block *sp) );
/* stats.c */
_PROTOTYPE( bit_t count_free_bits, (struct super_block *sp, int map));
_PROTOTYPE( void blockstats, (u32_t *total, u32_t *free, u32_t *avail));
/* time.c */
_PROTOTYPE( int fs_utime, (void) );

View file

@ -81,16 +81,17 @@ PUBLIC int fs_statvfs()
struct statvfs st;
struct super_block *sp;
int r, scale;
u32_t used;
sp = get_super(fs_dev);
scale = sp->s_log_zone_size;
blockstats(&st.f_blocks, &st.f_bfree, &used);
st.f_bavail = st.f_bfree;
st.f_bsize = sp->s_block_size << scale;
st.f_frsize = sp->s_block_size;
st.f_blocks = sp->s_zones << scale;
st.f_bfree = count_free_bits(sp, ZMAP) << scale;
st.f_bavail = st.f_bfree;
st.f_files = sp->s_ninodes;
st.f_ffree = count_free_bits(sp, IMAP);
st.f_favail = st.f_ffree;

View file

@ -85,3 +85,25 @@ int map; /* IMAP (inode map) or ZMAP (zone map) */
} while (--bcount > 0);
return free_bits; /* no bit could be allocated */
}
/*===========================================================================*
* blockstats *
*===========================================================================*/
PUBLIC void blockstats(u32_t *blocks, u32_t *free, u32_t *used)
{
struct super_block *sp;
int scale;
sp = get_super(fs_dev);
assert(sp);
scale = sp->s_log_zone_size;
*blocks = sp->s_zones << scale;
*free = count_free_bits(sp, ZMAP) << scale;
*used = *blocks - *free;
return;
}