You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by vo...@basf-it-services.com on 2003/04/27 18:57:43 UTC

Re: cvs commit: cocoon-2.1/src/deprecated/java/org/apache/cocoon/components/store MRUMemoryStore.java

Hi Vadim,

I think this will be a great improvement.

In cocoon.xconf the excalibur store is used which has a bad performance all
methods are synchronized an inside the synchronized block a store to the
persistent store can happen if the memory store is full. Arrrrggggggg very
very bad performance!!!

<role name="org.apache.excalibur.store.Store/TransientStore"
        shorthand="transient-store"
        default-class="org.apache.excalibur.store.impl.MRUMemoryStore"/>

I think is make sense to use your implementation or move your code to
excalibur before excalibur-store get released.

Thanks,

Volker

vgritsenko    2003/04/27 09:41:31

  Modified:    src/deprecated/java/org/apache/cocoon/components/store
                        MRUMemoryStore.java
  Log:
  Commit efficient MRU store implementation before it gets completely lost

  Revision  Changes    Path
  1.3       +42 -51
cocoon-2.1/src/deprecated/java/org/apache/cocoon/components/store/MRUMemoryStore.java


  Index: MRUMemoryStore.java
  ===================================================================
  RCS file:
/home/cvs/cocoon-2.1/src/deprecated/java/org/apache/cocoon/components/store/MRUMemoryStore.java,v

  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- MRUMemoryStore.java            27 Apr 2003 15:16:15 -0000
1.2
  +++ MRUMemoryStore.java            27 Apr 2003 16:41:31 -0000
1.3
  @@ -61,21 +61,24 @@
   import org.apache.avalon.framework.thread.ThreadSafe;

   import org.apache.cocoon.util.ClassUtils;
  +import org.apache.cocoon.util.MRUBucketMap;

   import java.io.IOException;
   import java.net.URLEncoder;
   import java.util.Enumeration;
  -import java.util.Hashtable;
  -import java.util.LinkedList;
   import java.util.NoSuchElementException;
  +import java.util.Iterator;
  +import java.util.Map;

   /**
    * This class provides a cache algorithm for the requested documents.
    * It combines a HashMap and a LinkedList to create a so called MRU
    * (Most Recently Used) cache.
    *
  - * The idea was taken from the "Writing Advanced Application Tutorial"
from
  - * javasoft. Many thanx to the writers!
  + * <p>This implementation is based on MRUBucketMap - map with efficient
  + * O(1) implementation of MRU removal policy.
  + *
  + * <p>TODO: Port improvments to the Excalibur implementation
    *
    * @deprecated Use the Avalon Excalibur Store instead.
    *
  @@ -89,8 +92,7 @@

       private int maxobjects;
       private boolean persistent;
  -    private Hashtable cache;
  -    private LinkedList mrulist;
  +    private MRUBucketMap cache;
       private Store persistentStore;
       private StoreJanitor storeJanitor;
       private ComponentManager manager;
  @@ -129,8 +131,7 @@
               throw new ParameterException("MRUMemoryStore maxobjects must
be at least 1!");
           }

  -        this.cache = new Hashtable((int)(this.maxobjects * 1.2));
  -        this.mrulist = new LinkedList();
  +        this.cache = new MRUBucketMap((int)(this.maxobjects * 1.2));
           this.storeJanitor.register(this);
       }

  @@ -151,12 +152,8 @@
                   if (getLogger().isDebugEnabled()) {
                       getLogger().debug("Final cache size: " +
this.cache.size());
                   }
  -                Enumeration enum = this.cache.keys();
  -                while (enum.hasMoreElements()) {
  -                    Object key = enum.nextElement();
  -                    if (key == null) {
  -                        continue;
  -                    }
  +                for (Iterator i = this.cache.keySet().iterator();
i.hasNext(); ) {
  +                    Object key = i.next();
                       try {
                           Object value = this.cache.remove(key);
                           if(checkSerializable(value)) {
  @@ -183,7 +180,7 @@
        * @param key The key for the object to store
        * @param value The object to store
        */
  -    public synchronized void store(Object key, Object value) {
  +    public void store(Object key, Object value) {
           this.hold(key,value);
       }

  @@ -195,21 +192,21 @@
        * @param key The key of the object to be stored
        * @param value The object to be stored
        */
  -    public synchronized void hold(Object key, Object value) {
  +    public void hold(Object key, Object value) {
           if (getLogger().isDebugEnabled()) {
               getLogger().debug("Holding object in memory:");
               getLogger().debug("  key: " + key);
               getLogger().debug("  value: " + value);
           }
  +
           /** ...first test if the max. objects in cache is reached... */
  -        while (this.mrulist.size() >= this.maxobjects) {
  +        while (this.cache.size() >= this.maxobjects) {
               /** ...ok, heapsize is reached, remove the last element...
*/
               this.free();
           }
  +
           /** ..put the new object in the cache, on the top of course ...
*/
           this.cache.put(key, value);
  -        this.mrulist.remove(key);
  -        this.mrulist.addFirst(key);
       }

       /**
  @@ -218,12 +215,9 @@
        * @param key The key of the requested object
        * @return the requested object
        */
  -    public synchronized Object get(Object key) {
  +    public Object get(Object key) {
           Object value = this.cache.get(key);
           if (value != null) {
  -            /** put the accessed key on top of the linked list */
  -            this.mrulist.remove(key);
  -            this.mrulist.addFirst(key);
               if (getLogger().isDebugEnabled()) {
                   getLogger().debug("Found key: " + key.toString());
               }
  @@ -239,12 +233,10 @@
               value = this.persistentStore.get(getFileName(key.toString
()));
               if (value != null) {
                   try {
  -                    if(!this.cache.containsKey(key)) {
  -                        this.hold(key, value);
  -                    }
  +                    this.hold(key, value);
                       return value;
                   } catch (Exception e) {
  -                    getLogger().error("Error in get()!", e);
  +                    getLogger().error("Error in hold()!", e);
                       return null;
                   }
               }
  @@ -258,13 +250,12 @@
        *
        * @param key The key of to be removed object
        */
  -    public synchronized void remove(Object key) {
  +    public void remove(Object key) {
           if (getLogger().isDebugEnabled()) {
               getLogger().debug("Removing object from store");
               getLogger().debug("  key: " + key);
           }
           this.cache.remove(key);
  -        this.mrulist.remove(key);
           if(this.persistent && key != null) {
               this.persistentStore.remove(getFileName(key.toString()));
           }
  @@ -276,12 +267,8 @@
        * @param key The key of the object
        * @return true if the key exists
        */
  -    public synchronized boolean containsKey(Object key) {
  -        if(persistent) {
  -            return (cache.containsKey(key) ||
persistentStore.containsKey(key));
  -        } else {
  -            return cache.containsKey(key);
  -        }
  +    public boolean containsKey(Object key) {
  +        return cache.containsKey(key) || (persistent &&
persistentStore.containsKey(key));
       }

       /**
  @@ -289,15 +276,25 @@
        *
        * @return the enumeration of the cache
        */
  -    public synchronized Enumeration keys() {
  -        return this.cache.keys();
  +    public Enumeration keys() {
  +        return new Enumeration() {
  +            private Iterator i = cache.keySet().iterator();
  +
  +            public boolean hasMoreElements() {
  +                return i.hasNext();
  +            }
  +
  +            public Object nextElement() {
  +                return i.next();
  +            }
  +        };
       }

       /**
        * Returns count of the objects in the store, or -1 if could not be
        * obtained.
        */
  -    public synchronized int size() {
  +    public int size() {
           return this.cache.size();
       }

  @@ -305,28 +302,23 @@
        * Frees some of the fast memory used by this store.
        * It removes the last element in the store.
        */
  -    public synchronized void free() {
  +    public void free() {
           try {
               if (this.cache.size() > 0) {
                   // This can throw NoSuchElementException
  -                Object key = this.mrulist.removeLast();
  -                Object value = this.cache.remove(key);
  -                if (value == null) {
  -                    getLogger().warn("Concurrency condition in free()");
  -                }
  -
  +                Map.Entry node = this.cache.removeLast();
                   if (getLogger().isDebugEnabled()) {
                       getLogger().debug("Freeing cache.");
  -                    getLogger().debug("  key: " + key);
  -                    getLogger().debug("  value: " + value);
  +                    getLogger().debug("  key: " + node.getKey());
  +                    getLogger().debug("  value: " + node.getValue());
                   }

                   if (this.persistent) {
                       // Swap object on fs.
  -                    if(checkSerializable(value)) {
  +                    if(checkSerializable(node.getValue())) {
                           try {
                               this.persistentStore.store(
  -                                getFileName(key.toString()), value);
  +                                getFileName(node.getKey().toString()),
node.getValue());
                           } catch(Exception e) {
                               getLogger().error("Error storing object on
fs", e);
                           }
  @@ -377,4 +369,3 @@
           return URLEncoder.encode(key.toString());
       }
   }
  -