A performance optimization, inspired by a conversation with Thor Simon:
- Keep a freelist of component buffer headers, defaulting to 8 headers per component (tunable with the CCDNBUF kernel compile option). - When allocating a component buffer, try to pull a header off the freelist first, falling back on MALLOC() if the freelist is empty. Use MALLOC() rather than malloc(), because it will attempt to short-cut the allocation before actually making a full-blown malloc() call. - Keep statistics on how many component buffer headers have been allocated and how many of those allocations have resulted in freelist misses. With these changes, I observed measurable decreases in system and wall clock time on operations on an 8G ccd, as well as a measurable drop in the time spent in ccdbuffer() (measured with kernel profiling).
This commit is contained in:
parent
e911ec0bfe
commit
9a815ed696
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: ccd.c,v 1.37 1997/01/30 03:32:56 thorpej Exp $ */
|
||||
/* $NetBSD: ccd.c,v 1.38 1997/01/30 04:00:52 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -132,14 +132,46 @@ struct ccdbuf {
|
||||
int cb_unit; /* target unit */
|
||||
int cb_comp; /* target component */
|
||||
int cb_flags; /* misc. flags */
|
||||
|
||||
#define CBF_MIRROR 0x01 /* we're for a mirror component */
|
||||
LIST_ENTRY(ccdbuf) cb_list; /* entry on freelist */
|
||||
};
|
||||
|
||||
#define getccdbuf() \
|
||||
((struct ccdbuf *)malloc(sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK))
|
||||
#define putccdbuf(cbp) \
|
||||
free((caddr_t)(cbp), M_DEVBUF)
|
||||
/* cb_flags */
|
||||
#define CBF_MIRROR 0x01 /* we're for a mirror component */
|
||||
|
||||
/*
|
||||
* Number of freelist buffers per component. Overridable in kernel
|
||||
* config file and patchable.
|
||||
*/
|
||||
#ifndef CCDNBUF
|
||||
#define CCDNBUF 8
|
||||
#endif
|
||||
int ccdnbuf = CCDNBUF;
|
||||
|
||||
/*
|
||||
* XXX Is it OK to wait here?
|
||||
* XXX maybe set up a timeout when we hit some lowater?
|
||||
* XXX --thorpej
|
||||
*/
|
||||
#define CCDGETBUF(cs, cbp) do { \
|
||||
(cs)->sc_ngetbuf++; \
|
||||
if (((cbp) = (cs)->sc_freelist.lh_first) != NULL) { \
|
||||
LIST_REMOVE((cbp), cb_list); \
|
||||
(cs)->sc_freecount--; \
|
||||
} else { \
|
||||
(cs)->sc_nmisses++; \
|
||||
MALLOC((cbp), struct ccdbuf *, \
|
||||
sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CCDPUTBUF(cs, cbp) do { \
|
||||
if ((cs)->sc_freecount == (cs)->sc_hiwat) { \
|
||||
FREE((cbp), M_DEVBUF); \
|
||||
} else { \
|
||||
LIST_INSERT_HEAD(&(cs)->sc_freelist, (cbp), cb_list); \
|
||||
(cs)->sc_freecount++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CCDLABELDEV(dev) \
|
||||
(MAKEDISKDEV(major((dev)), ccdunit((dev)), RAW_PART))
|
||||
@ -221,6 +253,7 @@ ccdinit(ccd, cpaths, p)
|
||||
struct partinfo dpart;
|
||||
struct ccdgeom *ccg = &cs->sc_geom;
|
||||
char tmppath[MAXPATHLEN];
|
||||
struct ccdbuf *cbp;
|
||||
int error;
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -410,6 +443,23 @@ ccdinit(ccd, cpaths, p)
|
||||
ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize);
|
||||
ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors;
|
||||
|
||||
/*
|
||||
* Allocate the component buffer header freelist. We allocate
|
||||
* ccdnbuf buffers per component.
|
||||
*/
|
||||
LIST_INIT(&cs->sc_freelist);
|
||||
cs->sc_hiwat = cs->sc_nccdisks * ccdnbuf;
|
||||
cs->sc_freecount = cs->sc_hiwat;
|
||||
for (ix = 0; ix < cs->sc_hiwat; ix++) {
|
||||
MALLOC(cbp, struct ccdbuf *, sizeof(struct ccdbuf),
|
||||
M_DEVBUF, M_WAITOK);
|
||||
LIST_INSERT_HEAD(&cs->sc_freelist, cbp, cb_list);
|
||||
}
|
||||
|
||||
/* Reset statistics. */
|
||||
cs->sc_nmisses = 0;
|
||||
cs->sc_ngetbuf = 0;
|
||||
|
||||
cs->sc_flags |= CCDF_INITED;
|
||||
cs->sc_cflags = ccd->ccd_flags; /* So we can find out later... */
|
||||
cs->sc_unit = ccd->ccd_unit;
|
||||
@ -808,7 +858,7 @@ ccdbuffer(cs, bp, bn, addr, bcount, cbpp)
|
||||
/*
|
||||
* Fill in the component buf structure.
|
||||
*/
|
||||
cbp = getccdbuf();
|
||||
CCDGETBUF(cs, cbp);
|
||||
cbp->cb_flags = 0;
|
||||
cbp->cb_buf.b_flags = bp->b_flags | B_CALL;
|
||||
cbp->cb_buf.b_iodone = ccdiodone;
|
||||
@ -847,7 +897,7 @@ ccdbuffer(cs, bp, bn, addr, bcount, cbpp)
|
||||
*/
|
||||
if ((cs->sc_cflags & CCDF_MIRROR) &&
|
||||
((cbp->cb_buf.b_flags & B_READ) == 0)) {
|
||||
cbp = getccdbuf();
|
||||
CCDGETBUF(cs, cbp);
|
||||
*cbp = *cbpp[0];
|
||||
cbp->cb_flags = CBF_MIRROR;
|
||||
cbp->cb_buf.b_dev = ci2->ci_dev; /* XXX */
|
||||
@ -924,7 +974,7 @@ ccdiodone(vbp)
|
||||
}
|
||||
count = cbp->cb_buf.b_bcount;
|
||||
cbflags = cbp->cb_flags;
|
||||
putccdbuf(cbp);
|
||||
CCDPUTBUF(cs, cbp);
|
||||
|
||||
/*
|
||||
* If all done, "interrupt".
|
||||
@ -1014,6 +1064,7 @@ ccdioctl(dev, cmd, data, flag, p)
|
||||
struct ccd_softc *cs;
|
||||
struct ccd_ioctl *ccio = (struct ccd_ioctl *)data;
|
||||
struct ccddevice ccd;
|
||||
struct ccdbuf *cbp;
|
||||
char **cpp;
|
||||
struct vnode **vpp;
|
||||
|
||||
@ -1165,6 +1216,12 @@ ccdioctl(dev, cmd, data, flag, p)
|
||||
free(cs->sc_cinfo[i].ci_path, M_DEVBUF);
|
||||
}
|
||||
|
||||
/* Free component buffer freelist. */
|
||||
while ((cbp = cs->sc_freelist.lh_first) != NULL) {
|
||||
LIST_REMOVE(cbp, cb_list);
|
||||
FREE(cbp, M_DEVBUF);
|
||||
}
|
||||
|
||||
/* Free interleave index. */
|
||||
for (i = 0; cs->sc_itable[i].ii_ndisk; ++i)
|
||||
free(cs->sc_itable[i].ii_index, M_DEVBUF);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: ccdvar.h,v 1.11 1996/02/28 01:08:32 thorpej Exp $ */
|
||||
/* $NetBSD: ccdvar.h,v 1.12 1997/01/30 04:00:53 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -78,6 +78,8 @@
|
||||
* @(#)cdvar.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
/*
|
||||
* Dynamic configuration and disklabel support by:
|
||||
* Jason R. Thorpe <thorpej@nas.nasa.gov>
|
||||
@ -174,6 +176,8 @@ struct ccdgeom {
|
||||
u_int32_t ccg_ncylinders; /* # cylinders per unit */
|
||||
};
|
||||
|
||||
struct ccdbuf;
|
||||
|
||||
/*
|
||||
* A concatenated disk is described after initialization by this structure.
|
||||
*/
|
||||
@ -189,6 +193,13 @@ struct ccd_softc {
|
||||
struct ccdgeom sc_geom; /* pseudo geometry info */
|
||||
char sc_xname[8]; /* XXX external name */
|
||||
struct disk sc_dkdev; /* generic disk device info */
|
||||
LIST_HEAD(, ccdbuf) sc_freelist; /* component buffer freelist */
|
||||
int sc_freecount; /* number of entries */
|
||||
int sc_hiwat; /* freelist high water mark */
|
||||
|
||||
/* Statistics */
|
||||
u_long sc_nmisses; /* number of freelist misses */
|
||||
u_long sc_ngetbuf; /* number of ccdbuf allocs */
|
||||
};
|
||||
|
||||
/* sc_flags */
|
||||
|
Loading…
Reference in New Issue
Block a user