Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 183 by [email protected]: Reclaiming the space of flushed items is needed.
http://code.google.com/p/memcached/issues/detail?id=183

What steps will reproduce the problem?
1. I found the problem in code review.
2.
3.

What is the expected output? What do you see instead?

The space of flushed items can be reused according to the following two cases. 1. do_item_get() unlinks the flushed item when the same key is used to get the item. 2. do_item_alloc() might evict the flushed items after fails both to find expired items and to allocate memory from slab allocator.

If the first case does not happen, the flushed items will be evicted according to the second case. In the second case, even if the flushed items exist, the do_item_alloc() tries to find only expired items. So, if there are only flushed items and no available memory in slabs, do_item_alloc() just wastes CPU resource to find reusable/free memory. And also, since the flushed items are evicted in the last phase of do_item_alloc(), eviction count is incremented. But, the semantic of reusing the space of flushed items should be reclaiming.

To solve the above problem,
the do_item_alloc() should reclaim the space of flushed items as well as
expired items in the first phase of it.
The needed code update is like followings.

item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_time_t exptime, const int nbytes) {

    . . .

    for (search = tails[id];
         tries > 0 && search != NULL;
         tries--, search=search->prev) {
#if 1 // NEW CODE
        if ((search->refcount == 0) &&
            ((search->exptime != 0 && search->exptime < current_time) ||
             (search->time < engine->config.oldest_live &&
              engine->config.oldest_live <= current_time)))
#else
        if (search->refcount == 0 &&
            (search->exptime != 0 && search->exptime < current_time))
#endif
        {
            it = search;
            /* I don't want to actually free the object, just steal
             * the item to avoid to grab the slab mutex twice ;-)
             */
            STATS_LOCK();
            stats.reclaimed++;
            STATS_UNLOCK();
            itemstats[id].reclaimed++;
            it->refcount = 1;
slabs_adjust_mem_requested(it->slabs_clsid, ITEM_ntotal(it), ntotal);
            do_item_unlink(it);
            /* Initialize the item block: */
            it->slabs_clsid = 0;
            it->refcount = 0;
            break;
        }
    }

    . . .

}

What version of the product are you using? On what operating system?

1.4.5 and maybe lower versions.

Please provide any additional information below.

Nothing..


Reply via email to