On Wed, 19 Nov 2003, Jean-Jacques Clar wrote:

> The heap in cache_pqueue is a max head, it always keep the object with
> the highest priority in its root position. The object with the highest
> priority is the one that is ejected when a new element has to be
> inserted when the cache is full (max nb of entities or size reached).

Right.

We could easily change cache_pqueue to be a minheap as you say, but then I
still don't think this would all be self-consistent, AND we'd then have a
priority queue where the item with the SMALLEST priority was the first one
to be dequeued, which I don't think makes sense.

> The return value of the set priority functions in mod_mem_cache.c:
> memcache_lru_algorithm(), memcache_gdsf_algorithm()  and the
> get_priority() function have to be consistent to make sure the heap is
> bubbling and percolating correctly.

I think this is the ultimate problem.  memcache_foo_algorithm() sets the
->priority to a positive value but then returns the negative of that
value.  This means that cache_update() in cache_cache.c will think the old
and new priorities are negative, as they should be, and thus
cache_pq_change_priority() will correctly select the
bubble_up/percolate_down *direction*.  But then when you get down into
those functions, they'll look up the priorities of the moving item and its
parents/children, which will be positive because the foo_algorithm
functions stored them that way and get_priority returns them without
negating them, and thus the bubble/percolate will never move the moving
item up or down at all.  This is bad.

I think your patch will work, but wouldn't it be easier to just have the
memcache_foo_algorithm() functions set the ->priority to a negative value
and then return the value they actually stored, rather than setting it to
a positive value and then returning its negative?

Then anybody who either called get_priority() or just looked at the
->priority field would get the same answer.

Eg, we could do this:
----------------
static long memcache_lru_algorithm(long queue_clock, void *a)
{
    cache_object_t *obj = (cache_object_t *)a;
    mem_cache_object_t *mobj = obj->vobj;
    if (mobj->priority == 0)
        mobj->priority = -((long)(queue_clock + mobj->total_refs));

    /*
     * a 'proper' LRU function would just be
     *  mobj->priority = mobj->total_refs;
     */
    return mobj->priority;
}
----------------
Instead of this:
----------------
static long memcache_lru_algorithm(long queue_clock, void *a)
{
    cache_object_t *obj = (cache_object_t *)a;
    mem_cache_object_t *mobj = obj->vobj;
    if (mobj->priority == 0)
        mobj->priority = ((long)(queue_clock + mobj->total_refs));

    /*
     * a 'proper' LRU function would just be
     *  mobj->priority = mobj->total_refs;
     */
    return -1*mobj->priority;
}
----------------

Thoughts?

--Cliff

Reply via email to