From: Matthew Dillon Date: Mon, 2 Jul 2007 06:34:26 +0000 (+0000) Subject: Because the objcache caches up to two magazines on each cpu some pretty X-Git-Tag: v2.0.1~2692 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/a1f6a1fea8ebbf0877601f90b27855771c3b13e2 Because the objcache caches up to two magazines on each cpu some pretty bad degenerate conditions will be hit if the cluster limit is set too small or the magazine size is set too large. Detect the problem and reduce the magazine size to compensate. If we hit the minimum magazine size (16), increase the cluster limit to compensate. Report the corrections on the console. We also have the option of stealing magazines from other cpus, or reducing the magazine size even further to handle extreme cases. This should solve most of the objcache issues when ncpus is set to 31. --- diff --git a/sys/kern/kern_objcache.c b/sys/kern/kern_objcache.c index c95aa5bbc8..515e265357 100644 --- a/sys/kern/kern_objcache.c +++ b/sys/kern/kern_objcache.c @@ -29,7 +29,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/kern_objcache.c,v 1.19 2007/05/29 17:01:04 dillon Exp $ + * $DragonFly: src/sys/kern/kern_objcache.c,v 1.20 2007/07/02 06:34:26 dillon Exp $ */ #include @@ -48,7 +48,7 @@ static MALLOC_DEFINE(M_OBJCACHE, "objcache", "Object Cache"); static MALLOC_DEFINE(M_OBJMAG, "objcache magazine", "Object Cache Magazine"); -#define INITIAL_MAG_CAPACITY 256 +#define INITIAL_MAG_CAPACITY 64 struct magazine { int rounds; @@ -131,6 +131,7 @@ struct objcache { void *allocator_args; SLIST_ENTRY(objcache) oc_next; + int exhausted; /* oops */ /* NUMA-cluster level caches */ struct magazinedepot depot[MAXCLUSTERS]; @@ -182,6 +183,8 @@ objcache_create(const char *name, int cluster_limit, int mag_capacity, struct objcache *oc; struct magazinedepot *depot; int cpuid; + int need; + int factor; /* allocate object cache structure */ oc = kmalloc(__offsetof(struct objcache, cache_percpu[ncpus]), @@ -202,19 +205,41 @@ objcache_create(const char *name, int cluster_limit, int mag_capacity, if (mag_capacity == 0) mag_capacity = INITIAL_MAG_CAPACITY; - depot->magcapacity = mag_capacity; /* * The cluster_limit must be sufficient to have three magazines per - * cpu. + * cpu. If we have a lot of cpus the mag_capacity might just be + * too big, reduce it if necessary. + * + * Each cpu can hold up to two magazines, with the remainder in the + * depot. If many objects are allocated fewer magazines are + * available. We have to make sure that each cpu has access to + * free objects until the object cache hits 75% of its limit. */ if (cluster_limit == 0) { depot->unallocated_objects = -1; } else { - if (cluster_limit < mag_capacity * ncpus * 3) - cluster_limit = mag_capacity * ncpus * 3; + factor = 8; + need = mag_capacity * ncpus * factor; + if (cluster_limit < need && mag_capacity > 16) { + kprintf("objcache(%s): too small for ncpus" + ", adjusting mag_capacity %d->", + name, mag_capacity); + while (need > cluster_limit && mag_capacity > 16) { + mag_capacity >>= 1; + need = mag_capacity * ncpus * factor; + } + kprintf("%d\n", mag_capacity); + } + if (cluster_limit < need) { + kprintf("objcache(%s): too small for ncpus" + ", adjusting cluster_limit %d->%d\n", + name, cluster_limit, need); + cluster_limit = need; + } depot->unallocated_objects = cluster_limit; } + depot->magcapacity = mag_capacity; oc->alloc = alloc; /* initialize per-cpu caches */ @@ -393,6 +418,10 @@ retry: } return(obj); } + if (oc->exhausted == 0) { + kprintf("Warning, objcache(%s): Exhausted!\n", oc->name); + oc->exhausted = 1; + } /* * Otherwise block if allowed to.