From: Sven Verdoolaege Date: Sun, 10 Apr 2011 08:57:11 +0000 (+0200) Subject: isl_blk: don't reuse overly large blocks for small allocations X-Git-Tag: isl-0.07~238 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4873addae63570d1bf3032a68cbdf828ba63d240;p=platform%2Fupstream%2Fisl.git isl_blk: don't reuse overly large blocks for small allocations We usually allocate a large number of small objects, but occasionally we may allocate one or more big objects. The original caching code could reuse a cached huge object for a small allocation. This is fine if the object would grow later, but if it remains small, then we may end up consuming and wasting a lot of memory, especially if these objects are long-lived. Now we only a memory block if it is at most twice as big as the desired size. This may result in some large objects sticking around in the cache, so we evict objects from the cache after a while. Finally, we don't reuse any cache elements for initially zero sized allocations, but instead check the cache when the objects first growns to a non-zero size. Signed-off-by: Sven Verdoolaege --- diff --git a/isl_blk.c b/isl_blk.c index d581f2d..0c1dae7 100644 --- a/isl_blk.c +++ b/isl_blk.c @@ -10,6 +10,9 @@ #include #include +/* The maximal number of cache misses before first element is evicted */ +#define ISL_BLK_MAX_MISS 100 + struct isl_blk isl_blk_empty() { struct isl_blk block; @@ -36,31 +39,7 @@ int isl_blk_is_error(struct isl_blk block) return block.size == -1 && block.data == NULL; } -struct isl_blk isl_blk_alloc(struct isl_ctx *ctx, size_t n) -{ - int i; - struct isl_blk block; - - if (ctx->n_cached) { - int best = 0; - for (i = 1; ctx->cache[best].size != n && i < ctx->n_cached; ++i) { - if (ctx->cache[best].size < n) { - if (ctx->cache[i].size > ctx->cache[best].size) - best = i; - } else if (ctx->cache[i].size >= n && - ctx->cache[i].size < ctx->cache[best].size) - best = i; - } - block = ctx->cache[best]; - if (--ctx->n_cached != best) - ctx->cache[best] = ctx->cache[ctx->n_cached]; - } else - block = isl_blk_empty(); - - return isl_blk_extend(ctx, block, n); -} - -struct isl_blk isl_blk_extend(struct isl_ctx *ctx, struct isl_blk block, +static struct isl_blk extend(struct isl_ctx *ctx, struct isl_blk block, size_t new_n) { int i; @@ -92,6 +71,48 @@ static void isl_blk_free_force(struct isl_ctx *ctx, struct isl_blk block) free(block.data); } +struct isl_blk isl_blk_alloc(struct isl_ctx *ctx, size_t n) +{ + int i; + struct isl_blk block; + + block = isl_blk_empty(); + if (n && ctx->n_cached) { + int best = 0; + for (i = 1; ctx->cache[best].size != n && i < ctx->n_cached; ++i) { + if (ctx->cache[best].size < n) { + if (ctx->cache[i].size > ctx->cache[best].size) + best = i; + } else if (ctx->cache[i].size >= n && + ctx->cache[i].size < ctx->cache[best].size) + best = i; + } + if (ctx->cache[best].size < 2 * n + 100) { + block = ctx->cache[best]; + if (--ctx->n_cached != best) + ctx->cache[best] = ctx->cache[ctx->n_cached]; + if (best == 0) + ctx->n_miss = 0; + } else if (ctx->n_miss++ >= ISL_BLK_MAX_MISS) { + isl_blk_free_force(ctx, ctx->cache[0]); + if (--ctx->n_cached != 0) + ctx->cache[0] = ctx->cache[ctx->n_cached]; + ctx->n_miss = 0; + } + } + + return extend(ctx, block, n); +} + +struct isl_blk isl_blk_extend(struct isl_ctx *ctx, struct isl_blk block, + size_t new_n) +{ + if (isl_blk_is_empty(block)) + return isl_blk_alloc(ctx, new_n); + + return extend(ctx, block, new_n); +} + void isl_blk_free(struct isl_ctx *ctx, struct isl_blk block) { if (isl_blk_is_empty(block) || isl_blk_is_error(block)) diff --git a/isl_ctx.c b/isl_ctx.c index 4ea7a70..5b37bf5 100644 --- a/isl_ctx.c +++ b/isl_ctx.c @@ -93,6 +93,7 @@ isl_ctx *isl_ctx_alloc_with_options(struct isl_arg *arg, void *user_opt) isl_int_init(ctx->normalize_gcd); ctx->n_cached = 0; + ctx->n_miss = 0; ctx->error = isl_error_none; diff --git a/isl_ctx_private.h b/isl_ctx_private.h index 45ff837..a943b24 100644 --- a/isl_ctx_private.h +++ b/isl_ctx_private.h @@ -18,6 +18,7 @@ struct isl_ctx { isl_int normalize_gcd; int n_cached; + int n_miss; struct isl_blk cache[ISL_BLK_CACHE_SIZE]; struct isl_hash_table name_hash;