[jbosscache-commits] JBoss Cache SVN: r5287 - in core/trunk/src: main/java/org/jboss/cache/config and 3 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Sat Feb 2 09:41:14 EST 2008


Author: manik.surtani at jboss.com
Date: 2008-02-02 09:41:13 -0500 (Sat, 02 Feb 2008)
New Revision: 5287

Modified:
   core/trunk/src/main/docbook/userguide/en/modules/configuration_reference.xml
   core/trunk/src/main/java/org/jboss/cache/config/Configuration.java
   core/trunk/src/main/java/org/jboss/cache/marshall/AbstractMarshaller.java
   core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java
   core/trunk/src/test/java/org/jboss/cache/marshall/CacheMarshaller200Test.java
   core/trunk/src/test/java/org/jboss/cache/marshall/CacheMarshallerTestBase.java
   core/trunk/src/test/java/org/jboss/cache/profiling/AbstractProfileTest.java
   core/trunk/src/test/java/org/jboss/cache/profiling/ProfileTest.java
Log:
Improved marshaller performance by removing reference counting (now optional)

Modified: core/trunk/src/main/docbook/userguide/en/modules/configuration_reference.xml
===================================================================
--- core/trunk/src/main/docbook/userguide/en/modules/configuration_reference.xml	2008-02-01 12:13:53 UTC (rev 5286)
+++ core/trunk/src/main/docbook/userguide/en/modules/configuration_reference.xml	2008-02-02 14:41:13 UTC (rev 5287)
@@ -706,6 +706,37 @@
                   </entry>
                </row>
 
+               <row>
+                  <entry>
+                     <para>UseReferenceCounting</para>
+                  </entry>
+
+                  <entry>
+                     <para>
+                        An optional parameter that is used to control how identical objects are marshalled. If reference
+                        counting is disabled, they are marshalled again and added to the stream. If reference counting
+                        is enabled,
+                        they are written once and a reference is written in subsequent instances.
+                     </para>
+                     <para>
+                        By default this is set to<literal>false</literal>. Set this to
+                        <literal>true</literal>
+                        if you use
+                        transactions and have a lot of operations per transaction. Naturally, there is no way to
+                        ascertain
+                        a definite threshold after which reference counting should be used. It is usually a tradeoff
+                        between
+                        network speed and larger data streams, and CPU overhead in generating references. It is best to
+                        profile
+                        with this enabled and disabled to determine which is best, but one thing for certain is that if
+                        you do
+                        not use transactions, or have transactions with just one or two operations, reference counting
+                        ought to
+                        be disabled.
+                     </para>
+                  </entry>
+               </row>
+
             </tbody>
          </tgroup>
       </informaltable>

Modified: core/trunk/src/main/java/org/jboss/cache/config/Configuration.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/config/Configuration.java	2008-02-01 12:13:53 UTC (rev 5286)
+++ core/trunk/src/main/java/org/jboss/cache/config/Configuration.java	2008-02-02 14:41:13 UTC (rev 5287)
@@ -25,10 +25,10 @@
       implements Cloneable
 {
    private static final long serialVersionUID = 5553791890144997466L;
-   private int numberOfNotifierThreads = 25;
 
    private Marshaller marshaller;
 
+
    public void setCacheMarshaller(Marshaller instance)
    {
       marshaller = instance;
@@ -187,6 +187,7 @@
    private String marshallerClass;
    private ShutdownHookBehavior shutdownHookBehavior = ShutdownHookBehavior.DEFAULT;
    private boolean useLazyDeserialization = true;
+   private boolean useReferenceCounting = false;
 
    // ------------------------------------------------------------------------------------------------------------
    //   SETTERS - MAKE SURE ALL SETTERS PERFORM testImmutability()!!!
@@ -491,6 +492,17 @@
       this.useLazyDeserialization = useLazyDeserialization;
    }
 
+   /**
+    * Sets whether reference counting should be used when marshalling remote calls.
+    *
+    * @since 2.1.0
+    */
+   public void setUseReferenceCounting(boolean b)
+   {
+      testImmutability("useReferenceCounting");
+      useReferenceCounting = b;
+   }
+
    // ------------------------------------------------------------------------------------------------------------
    //   GETTERS
    // ------------------------------------------------------------------------------------------------------------
@@ -679,16 +691,16 @@
       this.marshallerClass = marshallerClass;
    }
 
-   public int getNumberOfNotifierThreads()
+   /**
+    * Gets whether reference counting should be used when marshalling remote calls.
+    *
+    * @since 2.1.0
+    */
+   public boolean isUseReferenceCounting()
    {
-      return numberOfNotifierThreads;
+      return useReferenceCounting;
    }
 
-   public void setNumberOfNotifierThreads(int numberOfNotifierThreads)
-   {
-      this.numberOfNotifierThreads = numberOfNotifierThreads;
-   }
-
    /**
     * Returns a {@link java.net.URL} to a default JGroups configuration file.
     *
@@ -762,7 +774,7 @@
 
       if (lockParentForChildInsertRemove != that.lockParentForChildInsertRemove) return false;
 
-      if (numberOfNotifierThreads != that.numberOfNotifierThreads) return false;
+      if (useReferenceCounting != that.useReferenceCounting) return false;
 
       return true;
    }
@@ -797,7 +809,7 @@
       result = 29 * result + (runtimeConfig != null ? runtimeConfig.hashCode() : 0);
       result = 29 * result + (marshallerClass != null ? marshallerClass.hashCode() : 0);
       result = 29 * result + (lockParentForChildInsertRemove ? 1 : 0);
-      result = 29 * result + numberOfNotifierThreads;
+      result = 29 * result + (useReferenceCounting ? 1 : 0);
       return result;
    }
 

Modified: core/trunk/src/main/java/org/jboss/cache/marshall/AbstractMarshaller.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/marshall/AbstractMarshaller.java	2008-02-01 12:13:53 UTC (rev 5286)
+++ core/trunk/src/main/java/org/jboss/cache/marshall/AbstractMarshaller.java	2008-02-02 14:41:13 UTC (rev 5287)
@@ -45,6 +45,7 @@
    private Map<GlobalTransaction, Fqn> transactions = new ConcurrentHashMap<GlobalTransaction, Fqn>(16);
    protected Configuration configuration;
    protected ClassLoader defaultClassLoader;
+   protected boolean useRefs = false;
 
    @Inject
    void injectDependencies(RegionManager regionManager, Configuration configuration, @ComponentName("deployerClassLoader")ClassLoader defaultClassLoader)
@@ -59,6 +60,10 @@
    {
       this.useRegionBasedMarshalling = configuration.isUseRegionBasedMarshalling();
       this.defaultInactive = configuration.isInactiveOnStartup();
+
+      // ensure that if we are using CacheMarshaller200 - i.e., using replication version of 2.0.0 - reference counting is
+      // enabled, since this is always enabled in JBC 2.0.0.
+      this.useRefs = configuration.isUseReferenceCounting() || getClass().equals(CacheMarshaller200.class);
    }
 
    protected void initLogger()

Modified: core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java	2008-02-01 12:13:53 UTC (rev 5286)
+++ core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java	2008-02-02 14:41:13 UTC (rev 5287)
@@ -6,6 +6,7 @@
  */
 package org.jboss.cache.marshall;
 
+import org.jboss.cache.CacheException;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.Region;
 import static org.jboss.cache.Region.Status;
@@ -130,7 +131,7 @@
       }
       else
       {
-         Map<Integer, Object> refMap = new HashMap<Integer, Object>();
+         UnmarshalledReferences refMap = new UnmarshalledReferences();
          Object retValue = unmarshallObject(in, defaultClassLoader, refMap);
          if (trace) log.trace("Unmarshalled object " + retValue);
          return retValue;
@@ -140,7 +141,7 @@
    public void objectToObjectStream(Object o, ObjectOutputStream out, Fqn region) throws Exception
    {
       if (trace) log.trace("Marshalling object " + o);
-      Map<Object, Integer> refMap = new HashMap<Object, Integer>();
+      Map<Object, Integer> refMap = useRefs ? new HashMap<Object, Integer>() : null;
       ClassLoader toUse = defaultClassLoader;
       Thread current = Thread.currentThread();
       ClassLoader old = current.getContextClassLoader();
@@ -171,7 +172,7 @@
 
    protected Object objectFromObjectStreamRegionBased(ObjectInputStream in) throws Exception
    {
-      Map<Integer, Object> refMap = new HashMap<Integer, Object>();
+      UnmarshalledReferences refMap = useRefs ? new UnmarshalledReferences() : null;
       Object o = unmarshallObject(in, refMap);
       Fqn regionFqn = null;
       if (o == null)
@@ -283,7 +284,7 @@
       {
          out.writeByte(MAGICNUMBER_NULL);
       }
-      else if (refMap.containsKey(o))// see if this object has been marshalled before.
+      else if (useRefs && refMap.containsKey(o))// see if this object has been marshalled before.
       {
          out.writeByte(MAGICNUMBER_REF);
          writeReference(out, refMap.get(o));
@@ -311,13 +312,13 @@
       else if (o instanceof Fqn)
       {
          out.writeByte(MAGICNUMBER_FQN);
-         writeReference(out, createReference(o, refMap));
+         if (useRefs) writeReference(out, createReference(o, refMap));
          marshallFqn((Fqn) o, out, refMap);
       }
       else if (o instanceof GlobalTransaction)
       {
          out.writeByte(MAGICNUMBER_GTX);
-         writeReference(out, createReference(o, refMap));
+         if (useRefs) writeReference(out, createReference(o, refMap));
          marshallGlobalTransaction((GlobalTransaction) o, out, refMap);
       }
       else if (o instanceof IpAddress)
@@ -388,7 +389,7 @@
       else if (o instanceof String)
       {
          out.writeByte(MAGICNUMBER_STRING);
-         writeReference(out, createReference(o, refMap));
+         if (useRefs) writeReference(out, createReference(o, refMap));
          marshallString((String) o, out);
       }
       else if (o instanceof NodeDataMarker)
@@ -418,7 +419,7 @@
             log.trace("Warning: using object serialization for " + o.getClass());
          }
          out.writeByte(MAGICNUMBER_SERIALIZABLE);
-         writeReference(out, createReference(o, refMap));
+         if (useRefs) writeReference(out, createReference(o, refMap));
          out.writeObject(o);
       }
       else
@@ -514,7 +515,7 @@
 
    // --------- Unmarshalling methods
 
-   private Object unmarshallObject(ObjectInputStream in, ClassLoader loader, Map<Integer, Object> refMap) throws Exception
+   private Object unmarshallObject(ObjectInputStream in, ClassLoader loader, UnmarshalledReferences refMap) throws Exception
    {
       if (loader == null)
       {
@@ -536,26 +537,31 @@
       }
    }
 
-   private Object unmarshallObject(ObjectInputStream in, Map<Integer, Object> refMap) throws Exception
+   private Object unmarshallObject(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       byte magicNumber = in.readByte();
-      Integer reference;
+      Integer reference = 0;
       Object retVal;
       switch (magicNumber)
       {
          case MAGICNUMBER_NULL:
             return null;
          case MAGICNUMBER_REF:
-            reference = readReference(in);
-            if (!refMap.containsKey(reference))
+            if (useRefs)
             {
-               throw new IOException("Unable to locate object reference " + reference + " in byte stream!");
+               reference = readReference(in);
+               return refMap.getReferencedObject(reference);
+//               if (!refMap.containsKey(reference))
+//               {
+//                  throw new IOException("Unable to locate object reference " + reference + " in byte stream!");
+//               }
+//               return refMap.get(reference);
             }
-            return refMap.get(reference);
+            else break;
          case MAGICNUMBER_SERIALIZABLE:
-            reference = readReference(in);
+            if (useRefs) reference = readReference(in);
             retVal = in.readObject();
-            refMap.put(reference, retVal);
+            if (useRefs) refMap.putReferencedObject(reference, retVal);
             return retVal;
          case MAGICNUMBER_MARSHALLEDVALUE:
             MarshalledValue mv = new MarshalledValue();
@@ -565,14 +571,14 @@
             retVal = unmarshallMethodCall(in, refMap);
             return retVal;
          case MAGICNUMBER_FQN:
-            reference = readReference(in);
+            if (useRefs) reference = readReference(in);
             retVal = unmarshallFqn(in, refMap);
-            refMap.put(reference, retVal);
+            if (useRefs) refMap.putReferencedObject(reference, retVal);
             return retVal;
          case MAGICNUMBER_GTX:
-            reference = readReference(in);
+            if (useRefs) reference = readReference(in);
             retVal = unmarshallGlobalTransaction(in, refMap);
-            refMap.put(reference, retVal);
+            if (useRefs) refMap.putReferencedObject(reference, retVal);
             return retVal;
          case MAGICNUMBER_IPADDRESS:
             retVal = unmarshallIpAddress(in);
@@ -603,9 +609,9 @@
          case MAGICNUMBER_SHORT:
             return in.readShort();
          case MAGICNUMBER_STRING:
-            reference = readReference(in);
+            if (useRefs) reference = readReference(in);
             retVal = unmarshallString(in);
-            refMap.put(reference, retVal);
+            if (useRefs) refMap.putReferencedObject(reference, retVal);
             return retVal;
          case MAGICNUMBER_NODEDATA_MARKER:
             retVal = new NodeDataMarker();
@@ -628,9 +634,10 @@
             }
             throw new Exception("Unknown magic number " + magicNumber);
       }
+      throw new Exception("Unknown magic number " + magicNumber);
    }
 
-   private GravitateResult unmarshallGravitateResult(ObjectInputStream in, Map<Integer, Object> refMap) throws Exception
+   private GravitateResult unmarshallGravitateResult(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       Boolean found = (Boolean) unmarshallObject(in, refMap);
       if (found)
@@ -651,7 +658,7 @@
       return (String) in.readObject();
    }
 
-   private MethodCall unmarshallMethodCall(ObjectInputStream in, Map<Integer, Object> refMap) throws Exception
+   private MethodCall unmarshallMethodCall(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       short methodId = in.readShort();
       byte numArgs = in.readByte();
@@ -669,7 +676,7 @@
       return MethodCallFactory.create(methodId, args);
    }
 
-   private GlobalTransaction unmarshallGlobalTransaction(ObjectInputStream in, Map<Integer, Object> refMap) throws Exception
+   private GlobalTransaction unmarshallGlobalTransaction(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       GlobalTransaction gtx = new GlobalTransaction();
       long id = in.readLong();
@@ -679,7 +686,7 @@
       return gtx;
    }
 
-   Fqn unmarshallFqn(ObjectInputStream in, Map<Integer, Object> refMap) throws Exception
+   Fqn unmarshallFqn(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
 
       boolean isRoot = in.readBoolean();
@@ -692,7 +699,7 @@
          {
             elements.add(unmarshallObject(in, refMap));
          }
-         fqn = new Fqn(elements);
+         fqn = new Fqn(elements, true);
       }
       else
       {
@@ -708,7 +715,7 @@
       return ipAddress;
    }
 
-   private List unmarshallArrayList(ObjectInputStream in, Map refMap) throws Exception
+   private List unmarshallArrayList(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       int listSize = readUnsignedInt(in);
       List list = new ArrayList(listSize);
@@ -716,49 +723,49 @@
       return list;
    }
 
-   private List unmarshallLinkedList(ObjectInputStream in, Map refMap) throws Exception
+   private List unmarshallLinkedList(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       List list = new LinkedList();
       populateFromStream(in, refMap, list, readUnsignedInt(in));
       return list;
    }
 
-   private Map unmarshallHashMap(ObjectInputStream in, Map refMap) throws Exception
+   private Map unmarshallHashMap(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       Map map = new HashMap();
       populateFromStream(in, refMap, map);
       return map;
    }
 
-   private Map unmarshallMapCopy(ObjectInputStream in, Map<Integer, Object> refMap) throws Exception
+   private Map unmarshallMapCopy(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       // read in as a HashMap first
       Map m = unmarshallHashMap(in, refMap);
       return new MapCopy(m);
    }
 
-   private Map unmarshallTreeMap(ObjectInputStream in, Map refMap) throws Exception
+   private Map unmarshallTreeMap(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       Map map = new TreeMap();
       populateFromStream(in, refMap, map);
       return map;
    }
 
-   private Set unmarshallHashSet(ObjectInputStream in, Map refMap) throws Exception
+   private Set unmarshallHashSet(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       Set set = new HashSet();
       populateFromStream(in, refMap, set);
       return set;
    }
 
-   private Set unmarshallTreeSet(ObjectInputStream in, Map refMap) throws Exception
+   private Set unmarshallTreeSet(ObjectInputStream in, UnmarshalledReferences refMap) throws Exception
    {
       Set set = new TreeSet();
       populateFromStream(in, refMap, set);
       return set;
    }
 
-   private void populateFromStream(ObjectInputStream in, Map refMap, Map mapToPopulate) throws Exception
+   private void populateFromStream(ObjectInputStream in, UnmarshalledReferences refMap, Map mapToPopulate) throws Exception
    {
       int size = readUnsignedInt(in);
       for (int i = 0; i < size; i++)
@@ -767,7 +774,7 @@
       }
    }
 
-   private void populateFromStream(ObjectInputStream in, Map refMap, Set setToPopulate) throws Exception
+   private void populateFromStream(ObjectInputStream in, UnmarshalledReferences refMap, Set setToPopulate) throws Exception
    {
       int size = readUnsignedInt(in);
       for (int i = 0; i < size; i++)
@@ -776,7 +783,7 @@
       }
    }
 
-   private void populateFromStream(ObjectInputStream in, Map refMap, List listToPopulate, int listSize) throws Exception
+   private void populateFromStream(ObjectInputStream in, UnmarshalledReferences refMap, List listToPopulate, int listSize) throws Exception
    {
       for (int i = 0; i < listSize; i++)
       {
@@ -838,3 +845,48 @@
       out.writeLong(i);
    }
 }
+
+/**
+ * An efficient array-based list of referenced objects, using the reference id as a subscript for the array.
+ */
+class UnmarshalledReferences
+{
+   private ArrayList<Object> referencedObjects = new ArrayList<Object>();
+
+   /**
+    * Retrieves an object referenced by an id
+    *
+    * @param ref reference
+    * @return object
+    */
+   public Object getReferencedObject(int ref)
+   {
+      if (ref >= referencedObjects.size())
+         throw new CacheException("Attempting to look up a ref that hasn't been inserted yet");
+      return referencedObjects.get(ref);
+   }
+
+   /**
+    * Adds a referenced object to the list of references
+    *
+    * @param ref reference id
+    * @param o   object
+    */
+   public void putReferencedObject(int ref, Object o)
+   {
+      int sz = referencedObjects.size();
+      // if we are not adding the object to the end of the list, make sure we use a specific position
+      if (ref < sz)
+      {
+         referencedObjects.add(ref, o);
+         return;
+      }
+      else if (ref > sz)
+      {
+         // if we are adding the reference to a position beyond the end of the list, make sure we expand the list first.
+         // this can happen, weirdly enough, since marshallObject() can be called recursively, such as from marshallFqn().         
+         for (int i = sz; i < ref; i++) referencedObjects.add(null);
+      }
+      referencedObjects.add(o);
+   }
+}

Modified: core/trunk/src/test/java/org/jboss/cache/marshall/CacheMarshaller200Test.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/marshall/CacheMarshaller200Test.java	2008-02-01 12:13:53 UTC (rev 5286)
+++ core/trunk/src/test/java/org/jboss/cache/marshall/CacheMarshaller200Test.java	2008-02-02 14:41:13 UTC (rev 5287)
@@ -16,7 +16,6 @@
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.ExecutorService;
@@ -55,7 +54,7 @@
       assert magic == CacheMarshaller200.MAGICNUMBER_FQN;
 
       // now the chunks of an Fqn
-      Fqn f = cm200.unmarshallFqn(ois, new HashMap<Integer, Object>());
+      Fqn f = cm200.unmarshallFqn(ois, new UnmarshalledReferences());
 
       assert f.equals(Fqn.fromString("/hello"));
    }
@@ -126,7 +125,7 @@
                      assert in.readByte() == CacheMarshaller200.MAGICNUMBER_FQN : "The stream should start with an Fqn";
                      // discard the nest refId short
                      in.readShort();
-                     Fqn f = cm200.unmarshallFqn(in, new HashMap<Integer, Object>());
+                     Fqn f = cm200.unmarshallFqn(in, new UnmarshalledReferences());
                      assert region.equals(f) : "Should use the same region for the response as was used for the request!";
 
                   }

Modified: core/trunk/src/test/java/org/jboss/cache/marshall/CacheMarshallerTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/marshall/CacheMarshallerTestBase.java	2008-02-01 12:13:53 UTC (rev 5286)
+++ core/trunk/src/test/java/org/jboss/cache/marshall/CacheMarshallerTestBase.java	2008-02-02 14:41:13 UTC (rev 5287)
@@ -35,6 +35,7 @@
       c.setUseRegionBasedMarshalling(false);
       c.setInactiveOnStartup(false);
       c.setReplVersionString(currentVersion);
+      //c.setUseReferenceCounting(true);
       marshaller = createVAM(c, regionManager);
    }
 

Modified: core/trunk/src/test/java/org/jboss/cache/profiling/AbstractProfileTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/profiling/AbstractProfileTest.java	2008-02-01 12:13:53 UTC (rev 5286)
+++ core/trunk/src/test/java/org/jboss/cache/profiling/AbstractProfileTest.java	2008-02-02 14:41:13 UTC (rev 5287)
@@ -24,6 +24,7 @@
    {
       Configuration cfg = UnitTestCacheConfigurationFactory.createConfiguration(Configuration.CacheMode.REPL_SYNC);
       cache = new DefaultCacheFactory().createCache(cfg, false);
+      cfg.setUseReferenceCounting(false);
    }
 
    @AfterTest

Modified: core/trunk/src/test/java/org/jboss/cache/profiling/ProfileTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/profiling/ProfileTest.java	2008-02-01 12:13:53 UTC (rev 5286)
+++ core/trunk/src/test/java/org/jboss/cache/profiling/ProfileTest.java	2008-02-02 14:41:13 UTC (rev 5287)
@@ -36,7 +36,7 @@
    /*
       Test configuration options
     */
-   protected static final long DURATION = 2 * 60 * 1000;
+   protected static final long DURATION = 10 * 60 * 1000;
    protected static final int NUM_THREADS = 10;
    protected static final int MAX_RANDOM_SLEEP_MILLIS = 100;
    protected static final int MAX_DEPTH = 8;
@@ -112,6 +112,9 @@
       startup();
       warmup();
       doTest();
+
+      // wait for user exit
+      System.in.read();
    }
 
    /**




More information about the jbosscache-commits mailing list