FreeBSD'fy ZFS zlib zalloc/zfree callbacks.

The previous code came from OpenSolaris, which in my understanding require
allocation size to be known to free memory.  To store that size previous
code allocated additional 8 byte header.  But I have noticed that zlib
with present settings allocates 64KB context buffers for each call, that
could be efficiently cached by UMA, but addition of those 8 bytes makes
them fall back to physical RAM allocations, that cause huge overhead and
lock congestion on small blocks.  Since FreeBSD's free() does not have
the size argument, switching to it solves the problem, increasing write
speed to ZVOLs with 4KB block size and GZIP compression on my 40-threads
test system from ~60MB/s to ~600MB/s.

MFC after:	1 week
Sponsored by:	iXsystems, Inc.
This commit is contained in:
Alexander Motin 2019-10-29 21:25:19 +00:00
parent 67d0e29304
commit a4d5fcadd8

View File

@ -27,45 +27,28 @@
#include <sys/types.h>
#include <sys/cmn_err.h>
#include <sys/systm.h>
#include <sys/kobj.h>
#include <sys/kmem.h>
#include <sys/zmod.h>
#include <contrib/zlib/zlib.h>
#include <contrib/zlib/zutil.h>
struct zchdr {
uint_t zch_magic;
uint_t zch_size;
};
#define ZCH_MAGIC 0x3cc13cc1
/*ARGSUSED*/
static void *
zfs_zcalloc(void *opaque, uint_t items, uint_t size)
{
size_t nbytes = sizeof (struct zchdr) + items * size;
struct zchdr *z = kobj_zalloc(nbytes, KM_NOWAIT|KM_TMP);
void *ptr;
if (z == NULL)
return (NULL);
z->zch_magic = ZCH_MAGIC;
z->zch_size = nbytes;
return (z + 1);
ptr = malloc((size_t)items * size, M_SOLARIS, M_NOWAIT);
return ptr;
}
/*ARGSUSED*/
static void
zfs_zcfree(void *opaque, void *ptr)
{
struct zchdr *z = ((struct zchdr *)ptr) - 1;
if (z->zch_magic != ZCH_MAGIC)
panic("zcfree region corrupt: hdr=%p ptr=%p", (void *)z, ptr);
kobj_free(z, z->zch_size);
free(ptr, M_SOLARIS);
}
/*