cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Ard Schrijvers" <a.schrijv...@hippo.nl>
Subject RE: my doubts about the current CocoonStoreJanitor/StoreJanitorImpl
Date Tue, 18 Jul 2006 08:49:13 GMT
the StoreJanitorImpl is capable of deleting the entire memory part of the EHCache when JVM
is low on memory: The StoreJanitorImpl counts the number of keys in cache, and multiplies
this with the percent_to_free, to calculate the number of items to delete from cache...more
or less like

final List keys = this.cache.getKeysNoDuplicateCheck();
final Serializable key = (Serializable) keys.get(0);
this.cache.remove(key);

Now, the fact that getKeysNoDuplicateCheck() return a list of ALL keys (memoryStore + diskStore),
where keys.get(0) is always in the memoryStore because of

public final synchronized List getKeysNoDuplicateCheck() throws IllegalStateException {
        checkStatus();
        ArrayList allKeys = new ArrayList();
        List memoryKeySet = Arrays.asList(memoryStore.getKeyArray());
        allKeys.addAll(memoryKeySet);
        if (overflowToDisk) {
            List diskKeySet = Arrays.asList(diskStore.getKeyArray());
            allKeys.addAll(diskKeySet);
        }
        return allKeys;
    }

AND the fact that for the number of keys to delete, store.size() [store.size() = memoryStore.getKeyArray()
+ diskStore.getKeyArray() ] is used, it is quite likely you end up with an example like the
following:

1) JVM memory = low
2) percent_to_free = 10%
3) store.size() = 10.000 (though the memoryStore part = 1000 because maxobjects is set to
1000)

This implies, that the StoreJanitor removes the first 1000 cachekeys + responses, i.e, my
entire memoryStore. The JVM now is quite likely to have some memory cleared, but when requests
keep coming in, you will gain nothing but slow responses, and a JVM more likely to go down.


WDYT about the StoreJanitor only trying to free memory from EHDefaultStore AND do this by
adding keys (though, it is a little more specific: the algorithm when to add key is when [store.memorySize()
> maxobjects - #keys2free], then adding #keys2free + maxobjects - store.memorySize() keys
with responses like "". Adding this number of keys forces to remove other keys from memoryStore
to diskStore (when overflow-to-disk = true, otherwise they will be deleted), but now according
the correct eviction policy. In the end, the added keys with known "key" are removed from
cache again. If [store.memorySize() < maxobjects - #keys2free], this solution wont work,
and stick to the old one, but it also implies a wrongly configured application: you have either
not enough memory, or you maxobjects is to high)

Hope it is clear what I am trying to explain. I suppose I first have to explain why I think
something must be changed before sending in patches, right? 

Regards Ard

> 
> 
> Hello,
> 
> I am not sure if everybody is familiar with the 
> CocoonStoreJanitor/StoreJanitorImpl, but in short it tries to 
> free memory from cocoon's different caches, and does this 
> according some configuration. For example, 
> 
> <store-janitor logger="core.store.janitor">
>     <!-- How much free memory shall be available in the jvm -->
>     <parameter name="freememory" value="2048000"/>
>     <!-- Indicates the limit of the jvm memory consumption. 
> The default max
>          heapsize for Sun's JVM is (almost) 64Mb -->
>     <parameter name="heapsize" value="30000000"/>
>     <!-- How often shall the cleanup thread check memory -->
>     <parameter name="cleanupthreadinterval" value="10"/>
>     <!-- Experimental adaptive algorithm for cleanup interval
>     <parameter name="adaptivethreadinterval" value="true"/>
>     --> 
>     <!-- Indicates the thread priority of the cleanup thread -->
>     <parameter name="threadpriority" value="5"/>
>     <!-- How much percent of the elements of each registered Store
>          shall be removed when low on memory. Default 10% -->
>     <parameter name="percent_to_free" value="10"/>
>     <!-- Invoke the garbage collector when low memory is reached -->
>     <parameter name="invokegc" value="false"/>
> </store-janitor>
> 
> Now, suppose, the JVM is low on memory. Now, I am used to 
> have 3 stores in my apps, namely defaultTransientStore, 
> eventAwareTransientStore and the EHDefaultStore. I am not 
> sure how about projects of other people/companies, but I know 
> I can only get some memory free from the EHDefaultStore. The 
> other stores either store very small responses, or, like the 
> defaultTransientStore, it only caches a couple of xslt's, 
> which are needed for so many pages, that removing them makes 
> no sense. The StoreJanitorImpl just removes keys+responses 
> from one single cache at a time, and moves to the next cache 
> the next time. 
> 
> In my opinion, the StoreJanitorImpl makes my cocoon app even 
> worse than before freeing the cache memory is the following:
> 1) It removes from caches I think no gain is in
> 2) It removes cachekeys from the EHDefaultStore in the worst 
> possible way: because the eviction policy from ehcache is not 
> available from within the EHDefaultStore, cachekeys + 
> reponses are just removed by starting with index 0. These are 
> frequently the more important keys, which are regenerated on 
> the next request (so this request is uncached, making it even 
> harder for the JVM to stay away from OOM).
> 
> I have had an email conversation with Greg Luck about this, 
> the main developer from ehcache. Since you cannot remove 
> cachekeys + responses according the eviction policy defined 
> in the ehcache, he came up with the idea to add keys with 
> empty responses. 
> 
> So, in the StoreJanitor, I check now wether the store is 
> instanceof EHDefaultStore, and if so, and if the number of 
> keys in memoryStore is larger then the (maxobjects - limit) 
> (limit is computed in calcToFree(store) as the number of keys 
> to be removed), I add #limit number of keys with response "". 
> This means, that when maxobjects is reached, you can have 2 cases:
> 
> 1) overflowToDisk=true: the reponse is serialized to 
> diskStore, and the cachekey is moved to diskStore cachekey 
> array (by the way still in memory, but the response not anymore )
> 2) overflowToDisk=false: the cachekey + response is removed entirely
> 
> Now, at the end the added "dummy keys" are removed.
> 
> So, 
> 
> WDYT about this new way to free memory from the store. And 
> WDYT about only trying to free memory from the EHDefaultStore?
> 
> Regards Ard
> 
> -- 
> 
> Hippo
> Oosteinde 11
> 1017WT Amsterdam
> The Netherlands
> Tel  +31 (0)20 5224466
> -------------------------------------------------------------
> a.schrijvers@hippo.nl / http://www.hippo.nl
> -------------------------------------------------------------- 
> 

Mime
View raw message