Re: Chunked mempools, a first verdict

From: Andres Kroonmaa <andre@dont-contact.us>
Date: Thu, 3 May 2001 21:32:12 +0200

On 3 May 2001, at 11:59, Alex Rousskov <rousskov@measurement-factory.com> wrote:

> On Thu, 3 May 2001, Andres Kroonmaa wrote:
>
> > > If the interface is so complex that it requires N elements, either
> > > implement all N elements or simplify the interface.
> >
> > Simplify how?
>
> By decreasing N (i.e., supporting less features), of course. It is a
> trade-off, but writing "switch" functions is not a solution. Note that
> nowhere I said that we should simplify the interface, I just outlined
> the alternatives.

 By now I've already got it that we not after symbol name count. What
 actually had confused me nuts was counting all sort of src/ functions
 and wrappers as part of the API.

 To simplify API, simplest is to drop all stats, drop Tune functions,
 ie. hardcode idle limits and chunk size. Omit Init function, as all
 it does is zero out structs, can do this during first poolCreate call.
 What would be left is original 4 calls.

> I give up though. If the quality of the design is not important, there
> is no need for this discussion.

 But of course it is important, its just stupid me, I don't get those
 api things on the fly.
 So if we trash all the crap I've been trying, and look at the memPool
 library as the selfcontained "thing" that has N element interface,
 would you write it down this way:

/* Allocator API */
extern MemPool *memPoolCreate(const char *label, size_t obj_size);
extern void *memPoolAlloc(MemPool * pool);
extern void memPoolFree(MemPool * pool, void *obj);
extern void memPoolDestroy(MemPool * pool);

/* Tune API */
extern void memPoolSetChunkSize(MemPool * pool, size_t chunksize);
extern void memPoolSetIdleLimit(size_t new_idle_limit);

/* Stats API */
extern size_t memPoolGetIdleLimit(); /* might include in Totals */
extern int memPoolGetCount(); /* might be unnecessary */
extern MemPool *memPoolGetPool(int index);
extern int memPoolGetStats(MemPoolStats * stats, MemPool * pool);
extern int memPoolGetTotals(MemPoolTotals * stats);

/* Stats history API */
extern void memPoolCheckRates(); /* stats history checkpoints */
extern void memPoolUpdateTime(time_t time); /* better avoid */

/* Module housekeeping API */
extern void memPoolInit(void);
extern void memPoolClean(time_t maxage); /* maybe pass curtime also? */
 If we implement selfIniting, selfcleaning memPools, may omit both.

 That would be all. All else would be constructed from the
 primitives above.

 Is that now looking good?
 What would you add/remove?

 ----------------------------------------------------

/* Wrappers under src/mem.c */
/* NOT part of an API, so in terms of library API - irrelevant */
extern void memConfigure(void);
extern void memPoolCleanIdlePools(void *unused);
extern int memPoolInUseCount(MemPool * pool);
extern int memPoolsTotalAllocated(void);

/* cachemgr presenter, could also be moved into mem.c */
void memReport(StoreEntry *);

/* MemMeter */

extern void memMeterSyncHWater(MemMeter * m);
 This shouldn't be part of an API. Why not a macro?

void
memMeterSyncHWater(MemMeter * m)
{
    assert(m);
    if (m->hwater_level < m->level) {
        m->hwater_level = m->level;
        m->hwater_stamp = squid_curtime;
    }
}

#define memMeterCheckHWater(m) { if ((m).hwater_level < (m).level) memMeterSyncHWater(&(m)); }

 thats the only place its used in. IF() is redundant.

 Wouldn't that do:
#define memMeterCheckHWater(m) { \
   if ((m).hwater_level < (m).level) { \
        (m).hwater_level = (m).level; \
        (m).hwater_stamp = current_time; \
   } \
}

------------------------------------
 Andres Kroonmaa <andre@online.ee>
 CTO, Delfi Online
 Tel: 6501 731, Fax: 6501 708
 Pärnu mnt. 158, Tallinn,
 11317 Estonia
Received on Thu May 03 2001 - 13:36:50 MDT

This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:13:58 MST