kernel - Greatly improve shared memory fault rate concurrency / shared tokens
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 15 Nov 2011 09:02:24 +0000 (01:02 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 15 Nov 2011 09:04:56 +0000 (01:04 -0800)
commit54341a3b445fade1bbc473141893a7e06c06ccb5
tree54233f7f3e4186f516572c301bb14f92208a2c6d
parentd0d7dcc25c83f6be59849b3cabb25e1de22dda38
kernel - Greatly improve shared memory fault rate concurrency / shared tokens

This commit rolls up a lot of work to improve postgres database operations
and the system in general.  With this changes we can pgbench -j 8 -c 40 on
our 48-core opteron monster at 140000+ tps, and the shm vm_fault rate
hits 3.1M pps.

* Implement shared tokens.  They work as advertised, with some cavets.

  It is acceptable to acquire a shared token while you already hold the same
  token exclusively, but you will deadlock if you acquire an exclusive token
  while you hold the same token shared.

  Currently exclusive tokens are not given priority over shared tokens so
  starvation is possible under certain circumstances.

* Create a critical code path in vm_fault() using the new shared token
  feature to quickly fault-in pages which already exist in the VM cache.
  pmap_object_init_pt() also uses the new feature.

  This increases fault-in concurrency by a ridiculously huge amount,
  particularly on SHM segments (say when you have a large number of postgres
  clients).  Scaling for large numbers of clients on large numbers of
  cores is significantly improved.

  This also increases fault-in concurrency for MAP_SHARED file maps.

* Expand the breadn() and cluster_read() APIs.  Implement breadnx() and
  cluster_readx() which allows a getblk()'d bp to be passed.  If *bpp is not
  NULL a bp is being passed in, otherwise the routines call getblk().

* Modify the HAMMER read path to use the new API.  Instead of calling
  getcacheblk() HAMMER now calls getblk() and checks the B_CACHE flag.
  This gives getblk() a chance to regenerate a fully cached buffer from
  VM backing store without having to acquire any hammer-related locks,
  resulting in even faster operation.

* If kern.ipc.shm_use_phys is set to 2 the VM pages will be pre-allocated.
  This can take quite a while for a large map and also lock the machine
  up for a few seconds.  Defaults to off.

* Reorder the smp_invltlb()/cpu_invltlb() combos in a few places, running
  cpu_invltlb() last.

* An invalidation interlock might be needed in pmap_enter() under certain
  circumstances, enable the code for now.

* vm_object_backing_scan_callback() was failing to properly check the
  validity of a vm_object after acquiring its token.  Add the required
  check + some debugging.

* Make vm_object_set_writeable_dirty() a bit more cache friendly.

* The vmstats sysctl was scanning every process's vm_map (requiring a
  vm_map read lock to do so), which can stall for long periods of time
  when the system is paging heavily.  Change the mechanic to a LWP flag
  which can be tested with minimal locking.

* Have the phys_pager mark the page as dirty too, to make sure nothing
  tries to free it.

* Remove the spinlock in pmap_prefault_ok(), since we do not delete page
  table pages it shouldn't be needed.

* Add a required cpu_ccfence() in pmap_inval.c.  The code generated prior
  to this fix was still correct, and this makes sure it stays that way.

* Replace several manual wiring cases with calls to vm_page_wire().
59 files changed:
sys/gnu/vfs/ext2fs/ext2_alloc.c
sys/gnu/vfs/ext2fs/ext2_balloc.c
sys/gnu/vfs/ext2fs/ext2_inode.c
sys/gnu/vfs/ext2fs/ext2_linux_balloc.c
sys/gnu/vfs/ext2fs/ext2_linux_ialloc.c
sys/gnu/vfs/ext2fs/ext2_subr.c
sys/kern/lwkt_thread.c
sys/kern/lwkt_token.c
sys/kern/sysv_shm.c
sys/kern/usched_bsd4.c
sys/kern/vfs_bio.c
sys/kern/vfs_cluster.c
sys/platform/pc32/i386/pmap.c
sys/platform/pc64/x86_64/pmap.c
sys/platform/pc64/x86_64/pmap_inval.c
sys/platform/vkernel/platform/pmap.c
sys/platform/vkernel64/platform/pmap.c
sys/sys/buf.h
sys/sys/buf2.h
sys/sys/globaldata.h
sys/sys/proc.h
sys/sys/thread.h
sys/sys/thread2.h
sys/vfs/hammer/hammer_io.c
sys/vfs/hammer/hammer_ondisk.c
sys/vfs/hammer/hammer_vnops.c
sys/vfs/hammer/hammer_volume.c
sys/vfs/hpfs/hpfs_alsubr.c
sys/vfs/hpfs/hpfs_subr.c
sys/vfs/hpfs/hpfs_vfsops.c
sys/vfs/hpfs/hpfs_vnops.c
sys/vfs/isofs/cd9660/cd9660_lookup.c
sys/vfs/isofs/cd9660/cd9660_rrip.c
sys/vfs/isofs/cd9660/cd9660_vfsops.c
sys/vfs/isofs/cd9660/cd9660_vnops.c
sys/vfs/msdosfs/msdosfs_denode.c
sys/vfs/msdosfs/msdosfs_fat.c
sys/vfs/msdosfs/msdosfs_lookup.c
sys/vfs/msdosfs/msdosfs_vfsops.c
sys/vfs/ntfs/ntfs_subr.c
sys/vfs/ntfs/ntfs_vfsops.c
sys/vfs/ntfs/ntfs_vnops.c
sys/vfs/tmpfs/tmpfs_vnops.c
sys/vfs/udf/udf_vfsops.c
sys/vfs/ufs/ffs_alloc.c
sys/vfs/ufs/ffs_balloc.c
sys/vfs/ufs/ffs_inode.c
sys/vfs/ufs/ffs_subr.c
sys/vfs/ufs/ffs_vfsops.c
sys/vfs/userfs/userfs_vnops.c
sys/vm/phys_pager.c
sys/vm/vm_fault.c
sys/vm/vm_kern.c
sys/vm/vm_map.h
sys/vm/vm_meter.c
sys/vm/vm_object.c
sys/vm/vm_object.h
sys/vm/vm_page.c
sys/vm/vm_page.h