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
> -------------------------------------------------------------
> [EMAIL PROTECTED] / http://www.hippo.nl
> --------------------------------------------------------------
>