Am 19.01.2007 um 17:38 schrieb Stephen Deasey:
I don't think it's 100% accurate to say memory just bloats and bloats! All caches have an upper bound. A 10MB cache will not grow beyond 10MB.
Yes. It is not 100% accurate.
Looks like you have a different situation though. Your cache is sized large enough to hold all data, but the usual working set is much smaller. With the fancy new memory allocator that returns memory to the OS, you'd like to prune the cache of expired entries even though the cache is still below it's configured max size.
Actually, the situation is: I have a large database (not SQL) and I cache some visited rows in the ns_cache. During the session user may cache number of rows but not visit them any more, hence they will stay in the cache forever. It may be that most of the cache is just old-data but it is kept there for no reason.
I removed this functionality from the old code! I'm fine with it being put back, but there were a couple of problems with the old code worth mentioning. In the old code, caches were either size limited *or* time limited, but not both. With a time limited cache therefore you had to have a sweeper thread to clear out expired entries or it would indeed bloat and bloat... Unfortunately, if a load spike occurred in between a sweep then the cache would grow until the server aborts. Another problem (if I'm remembering this right) was that the sweep interval was the same as the expiry time for entries, which was specified at cache creation time. So if you had a large cache with a short expiry time, frequently a thread would be created, lock the cache, scan through all the entries, maybe evict a few, then unlock the cache. And then do it again a moment later.
OK. No automatism. I'm also OK if I can run that by hand on points in time.
So for a new sweeper, maybe the way to handle it is to create Ns_CacheFlushExpired() which can be passed to Ns_ScheduleProc(). C code can handle the period manually. For Tcl, add a new switch to ns_cache_create, -expireflush (or whatever). Keep the -expire and -expireflush times distinct. Tcl caches live forever IIRC so that's all there is to it, no need to handle unregistering the scheduled proc.
Why not just ns_cache_flush ?-expired? cache Programmer may invoke that anytime it wishes. Actually, only the Tcl wrapper needs to be done that will step each entry from the cache but not return any values. The cache code will take care to expire old items as it walks the cache. I cannot comment about having single LRU list for all the caches. It sounds like more work than I can afford. A simple "-expired" flag would be sufficient. But, the idea seems OK as it would free me from "guessing" on how large each cache would/should be.