diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index e39654ea067..8710f9517d7 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -701,6 +701,13 @@ bucket_cache_drain(uma_zone_t zone) bucket_free(zone, bucket, NULL); ZONE_LOCK(zone); } + + /* + * Shrink further bucket sizes. Price of single zone lock collision + * is probably lower then price of global cache drain. + */ + if (zone->uz_count > zone->uz_count_min) + zone->uz_count--; } static void @@ -1461,6 +1468,7 @@ zone_ctor(void *mem, int size, void *udata, int flags) zone->uz_fails = 0; zone->uz_sleeps = 0; zone->uz_count = 0; + zone->uz_count_min = 0; zone->uz_flags = 0; zone->uz_warning = NULL; timevalclear(&zone->uz_ratecheck); @@ -1552,6 +1560,7 @@ out: zone->uz_count = bucket_select(zone->uz_size); else zone->uz_count = BUCKET_MAX; + zone->uz_count_min = zone->uz_count; return (0); } diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h index 00e8519e07c..1ffc7d5fabb 100644 --- a/sys/vm/uma_int.h +++ b/sys/vm/uma_int.h @@ -300,7 +300,8 @@ struct uma_zone { volatile u_long uz_fails; /* Total number of alloc failures */ volatile u_long uz_frees; /* Total number of frees */ uint64_t uz_sleeps; /* Total number of alloc sleeps */ - uint16_t uz_count; /* Highest amount of items in bucket */ + uint16_t uz_count; /* Amount of items in full bucket */ + uint16_t uz_count_min; /* Minimal amount of items there */ /* The next three fields are used to print a rate-limited warnings. */ const char *uz_warning; /* Warning to print on failure */