You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gc...@apache.org on 2008/01/19 01:45:45 UTC

svn commit: r613331 - in /myfaces/trinidad/trunk/trinidad-api/src/main: java-templates/org/apache/myfaces/trinidad/component/ java/org/apache/myfaces/trinidad/component/

Author: gcrawford
Date: Fri Jan 18 16:45:44 2008
New Revision: 613331

URL: http://svn.apache.org/viewvc?rev=613331&view=rev
Log:
Issue 906 optimize getClientId - use per thread shared StringBuilder

In getClientId/getContainerClientId we create a new stringBuilder.

However when creating a client id we only use one stringBuilder at a time, so have a single instance of a StringBuilder saved on thread local.

Have a utility to get this instance, and any time a user gets the instance, set the length of the stringBuilder to 0. 

Modified:
    myfaces/trinidad/trunk/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java?rev=613331&r1=613330&r2=613331&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java-templates/org/apache/myfaces/trinidad/component/UIXDecorateCollectionTemplate.java Fri Jan 18 16:45:44 2008
@@ -6,9 +6,9 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- * 
+ *
  *  http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -26,7 +26,7 @@
  * <p>
  * @version $Name:  $ ($Revision$) $Date$
  */
-public abstract class UIXDecorateCollectionTemplate extends UIXComponentBase 
+public abstract class UIXDecorateCollectionTemplate extends UIXComponentBase
         implements NamingContainer
 {
   /**
@@ -38,13 +38,13 @@
   {
     return _currencyString;
   }
-  
+
   /**
    * Sets the currency String for this decorate collection. The decorator renders
    * aggregated components that are not in the component tree. If any of the aggregated
    * component is a naming container (for e.g. menubar), this method allows the currency to
    * be set to that naming container so that it can successfully decode its children.
-   * 
+   *
    * @param currency the currency to be established
    * @see #getCurrencyString
    */
@@ -52,7 +52,7 @@
   {
     _currencyString = currency;
   }
-  
+
   /**
    * Gets the client-id of this component, without any NamingContainers.
    * This id changes depending on the currency Object.
@@ -69,7 +69,9 @@
     String key = getCurrencyString();
     if (key != null)
     {
-      id += NamingContainer.SEPARATOR_CHAR + key;
+      StringBuilder bld = __getSharedStringBuilder();
+      bld.append(id).append(NamingContainer.SEPARATOR_CHAR).append(key);
+      id = bld.toString();
     }
 
     return id;

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java?rev=613331&r1=613330&r2=613331&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java Fri Jan 18 16:45:44 2008
@@ -6,9 +6,9 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- * 
+ *
  *  http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -555,9 +555,9 @@
   @Deprecated
   public String getCurrencyString()
   {
-    return getClientRowKey();  
+    return getClientRowKey();
   }
-  
+
   /**
    * @deprecated use setClientRowKey
    * @see #setClientRowKey
@@ -667,7 +667,9 @@
     String key = getClientRowKey();
     if (key != null)
     {
-      id += NamingContainer.SEPARATOR_CHAR + key;
+      StringBuilder bld = __getSharedStringBuilder();
+      bld.append(id).append(NamingContainer.SEPARATOR_CHAR).append(key);
+      id = bld.toString();
     }
 
     return id;
@@ -814,11 +816,11 @@
         if ((singleFacetState == null) ||
             (singleFacetState == Transient.TRUE))
           continue;
-        
+
         // Don't bother allocating anything until we have some non-null
         // and non-transient facet state
         if (facetStateIsEmpty)
-        {          
+        {
           facetStateIsEmpty = false;
           facetState = new Object[facetCount * 2];
         }
@@ -829,7 +831,7 @@
         facetState[base + 1] = singleFacetState;
         i++;
       }
-      
+
       // OK, we had something:  allocate the state array to three
       // entries, and insert the facet state at position 2
       if (!facetStateIsEmpty)
@@ -883,7 +885,7 @@
     // Just a transient component - return
     if ((stampState == Transient.TRUE) || (stampState == null))
       return;
-    
+
     // If this isn't an Object array, then it's a component with state
     // of its own, but no child/facet state - so restore and be done
     if (!(stampState instanceof Object[]))
@@ -905,7 +907,7 @@
     if (stateSize >= 3)
     {
       Object[] facetStateArray = (Object[]) state[2];
-      // This had better be non-null, otherwise we never 
+      // This had better be non-null, otherwise we never
       // should have allocated a three-element array!
       assert(facetStateArray != null);
 
@@ -917,7 +919,7 @@
           restoreStampState(context, stamp.getFacet(facetName), facetState);
       }
     }
-    
+
     // If there's any child state, restore it
     if (stateSize >= 2)
     {
@@ -976,7 +978,7 @@
 
   /**
    * Gets the ClientRowKeyManager that is used to handle the
-   * {@link #getClientRowKey} and  
+   * {@link #getClientRowKey} and
    * {@link #setClientRowKey} methods.
    * If the manager does not already exist a new one is created.
    * In order to create your own manager, your Renderer (for this component)
@@ -987,7 +989,7 @@
   {
     // this method must be public, because specific renderers
     // need access to the ClientRowKeyManager so that they might prune it.
-    
+
     InternalState iState = _getInternalState(true);
     if (iState._clientKeyMgr == null)
     {
@@ -1171,7 +1173,7 @@
   {
     // Never read and created by _getStampState
     //InternalState iState = _getInternalState(true);
-    
+
     StampState stampState = _getStampState();
     FacesContext context = getFacesContext();
     Object currencyObj = getRowKey();
@@ -1299,7 +1301,7 @@
     {
       if (_isOptimizedKey(clientRowKey))
         return clientRowKey;
-      
+
       ValueMap<Object,String> currencyCache = _currencyCache;
       Object rowkey = currencyCache.getKey(clientRowKey);
       return rowkey;
@@ -1319,7 +1321,7 @@
       if (key == null)
       {
         // we don't have a string-key, so create a new one.
-        
+
         // first check to see if the rowkey itself can be used as the string-key:
         if (rowKey instanceof String)
         {

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java?rev=613331&r1=613330&r2=613331&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java Fri Jan 18 16:45:44 2008
@@ -270,7 +270,7 @@
       if (containerComponent instanceof NamingContainer)
       {
         String contClientId = containerComponent.getClientId(context);
-        StringBuilder bld = new StringBuilder(contClientId.length() + 1 + clientId.length());
+        StringBuilder bld = __getSharedStringBuilder();
         bld.append(contClientId).append(NamingContainer.SEPARATOR_CHAR).append(clientId);
         clientId = bld.toString();
         break;
@@ -1198,6 +1198,59 @@
     }
   }
 
+
+
+  /**
+   * <p>
+   * This gets a single threadlocal shared stringbuilder instance, each time you call
+   * __getSharedStringBuilder it sets the length of the stringBuilder instance to 0.
+   * </p><p>
+   * This allows you to use the same StringBuilder instance over and over.
+   * You must call toString on the instance before calling __getSharedStringBuilder again.
+   * </p>
+   * Example that works
+   * <pre><code>
+   * StringBuilder sb1 = __getSharedStringBuilder();
+   * sb1.append(a).append(b);
+   * String c = sb1.toString();
+   *
+   * StringBuilder sb2 = __getSharedStringBuilder();
+   * sb2.append(b).append(a);
+   * String d = sb2.toString();
+   * </code></pre>
+   * <br><br>
+   * Example that doesn't work, you must call toString on sb1 before
+   * calling __getSharedStringBuilder again.
+   * <pre><code>
+   * StringBuilder sb1 = __getSharedStringBuilder();
+   * StringBuilder sb2 = __getSharedStringBuilder();
+   *
+   * sb1.append(a).append(b);
+   * String c = sb1.toString();
+   *
+   * sb2.append(b).append(a);
+   * String d = sb2.toString();
+   * </code></pre>
+   *
+   */
+  static StringBuilder __getSharedStringBuilder()
+  {
+    StringBuilder sb = _STRING_BUILDER.get();
+
+    if (sb == null)
+    {
+      sb = new StringBuilder();
+      _STRING_BUILDER.set(sb);
+    }
+
+    // clear out the stringBuilder by setting the length to 0
+    sb.setLength(0);
+
+    return sb;
+  }
+
+
+
   /**
    * render a component. this is called by renderers whose
    * getRendersChildren() return true.
@@ -1328,6 +1381,11 @@
 
   private static final Iterator<String> _EMPTY_STRING_ITERATOR =
     new EmptyIterator<String>();
+
+
+  static private final ThreadLocal<StringBuilder> _STRING_BUILDER =
+                                                        new ThreadLocal<StringBuilder>();
+
 
   private static final Iterator<UIComponent> _EMPTY_UICOMPONENT_ITERATOR =
     new EmptyIterator<UIComponent>();