Author: alexsmirnov
Date: 2009-01-05 21:38:39 -0500 (Mon, 05 Jan 2009)
New Revision: 12128
Modified:
trunk/framework/impl/src/main/java/org/ajax4jsf/application/AjaxStateHolder.java
trunk/framework/impl/src/main/java/org/ajax4jsf/application/ComponentsLoaderImpl.java
trunk/framework/impl/src/main/java/org/ajax4jsf/application/TreeStructureNode.java
trunk/framework/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
trunk/framework/jsf-test/pom.xml
trunk/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebResponse.java
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingConnection.java
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingHttpResponse.java
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingServer.java
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ResourceServiceThreadsTestCase.java
Log:
some state saving performance improvments
Modified:
trunk/framework/impl/src/main/java/org/ajax4jsf/application/AjaxStateHolder.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/application/AjaxStateHolder.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/application/AjaxStateHolder.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.Serializable;
+import java.lang.ref.WeakReference;
import java.util.Map;
import javax.faces.context.ExternalContext;
@@ -45,12 +46,12 @@
private static final long serialVersionUID = 6414488517358423537L;
private static final String STATE_HOLDER = AjaxStateHolder.class.getName();
- private final LRUMap<String,LRUMap<String, Object[]>> views;
+ private final LRUMap<String, LRUMap<String, StateReference>> views;
private final int numberOfViews;
private AjaxStateHolder(int capacity, int numberOfViews) {
- views = new LRUMap<String,LRUMap<String, Object[]>>(capacity);
+ views = new LRUMap<String, LRUMap<String, StateReference>>(capacity+1);
this.numberOfViews = numberOfViews;
}
@@ -61,7 +62,7 @@
}
ExternalContext externalContext = context.getExternalContext();
Object session = externalContext.getSession(true);
- Map<String,Object> sessionMap = externalContext.getSessionMap();
+ Map<String, Object> sessionMap = externalContext.getSessionMap();
if (_log.isDebugEnabled()) {
_log.debug("Request for a view states holder instance");
}
@@ -90,8 +91,11 @@
return instance;
}
- /* (non-Javadoc)
- * @see org.ajax4jsf.application.StateHolder#getState(java.lang.String,
java.lang.Object)
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.ajax4jsf.application.StateHolder#getState(java.lang.String,
+ * java.lang.Object)
*/
public Object[] getState(String viewId, String sequence) {
if (null == viewId) {
@@ -100,26 +104,33 @@
}
Object state[] = null;
synchronized (views) {
- LRUMap<String,Object[]> viewVersions = views.get(viewId);
+ LRUMap<String, StateReference> viewVersions = views.get(viewId);
if (null != viewVersions) {
if (null != sequence) {
- state = viewVersions.get(sequence);
+ StateReference stateReference = viewVersions.get(sequence);
+ if (null != stateReference) {
+ state = stateReference.getState();
+ }
}
if (null == state) {
if (_log.isDebugEnabled()) {
- _log.debug("No saved view state for sequence "+sequence);
+ _log.debug("No saved view state for sequence "
+ + sequence);
}
-// state = viewVersions.getMostRecent();
+ // state = viewVersions.getMostRecent();
}
} else if (_log.isDebugEnabled()) {
- _log.debug("No saved view states for viewId "+viewId);
+ _log.debug("No saved view states for viewId " + viewId);
}
}
return state;
}
- /* (non-Javadoc)
- * @see org.ajax4jsf.application.StateHolder#saveState(java.lang.String,
java.lang.Object, java.lang.Object)
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.ajax4jsf.application.StateHolder#saveState(java.lang.String,
+ * java.lang.Object, java.lang.Object)
*/
public void saveState(String viewId, String sequence, Object[] state) {
if (null == viewId) {
@@ -132,23 +143,35 @@
}
if (null != state) {
if (_log.isDebugEnabled()) {
- _log.debug("Save new viewState in session for viewId "+viewId+" and
sequence "+sequence);
+ _log.debug("Save new viewState in session for viewId " + viewId
+ + " and sequence " + sequence);
}
synchronized (views) {
- LRUMap<String,Object[]> viewVersions = views.get(viewId);
+ LRUMap<String, StateReference> viewVersions = views.get(viewId);
+ StateReference stateReference = null;
if (null == viewVersions) {
// TODO - make size parameter configurable
- viewVersions = new LRUMap<String,Object[]>(this.numberOfViews);
+ viewVersions = new LRUMap<String, StateReference>(
+ this.numberOfViews+1);
views.put(viewId, viewVersions);
+ stateReference = new StateReference(state);
+ viewVersions.put(sequence, stateReference);
+ } else {
+ stateReference = viewVersions.get(sequence);
+ if(null == stateReference){
+ stateReference = new StateReference(state);
+ viewVersions.put(sequence, stateReference);
+ } else {
+ stateReference.setState(state);
+ }
}
- viewVersions.put(sequence, state);
}
}
}
-
+
private void writeObject(java.io.ObjectOutputStream stream)
- throws IOException {
+ throws IOException {
synchronized (views) {
stream.defaultWriteObject();
@@ -156,8 +179,29 @@
}
private void readObject(java.io.ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ throws IOException, ClassNotFoundException {
stream.defaultReadObject();
}
+
+ @SuppressWarnings("serial")
+ private static class StateReference implements Serializable {
+ private Object[] state;
+
+ public Object[] getState() {
+ return state;
+ }
+
+ public void setState(Object[] state) {
+ this.state = state;
+ }
+
+ /**
+ * @param state
+ */
+ public StateReference(Object[] state) {
+ super();
+ this.state = state;
+ }
+ }
}
Modified:
trunk/framework/impl/src/main/java/org/ajax4jsf/application/ComponentsLoaderImpl.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/application/ComponentsLoaderImpl.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/application/ComponentsLoaderImpl.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -20,79 +20,60 @@
*/
package org.ajax4jsf.application;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
-import org.apache.commons.collections.Transformer;
-import org.apache.commons.collections.map.LazyMap;
-
/**
* @author asmirnov
*
*/
-public class ComponentsLoaderImpl implements Transformer, ComponentsLoader {
+public class ComponentsLoaderImpl implements ComponentsLoader {
- private volatile Map classes;
+ private Map<String, Class<? extends UIComponent>> classes;
- private ClassLoader loader;
+ private ClassLoader loader;
- public ComponentsLoaderImpl() {
- classes = Collections.synchronizedMap(LazyMap.decorate(new HashMap(),
- this));
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
org.ajax4jsf.portlet.application.ComponentsLoader#createComponent(java.lang.String)
- */
- public UIComponent createComponent(String type) {
- // Classes is a lazy Map, new object will be create on the fly.
- Class componentClass = (Class) classes.get(type);
- try {
- return (UIComponent) componentClass.newInstance();
- } catch (InstantiationException e) {
- throw new FacesException(
- "Error on create new instance of the component with class "
- + type, e);
- } catch (IllegalAccessException e) {
- throw new FacesException(
- "IllegalAccess on attempt to create new instance of the component with class
"
- + type, e);
+ public ComponentsLoaderImpl() {
+ classes = new ConcurrentHashMap<String, Class<? extends UIComponent>>(
+ 64);
+ loader = Thread.currentThread().getContextClassLoader();
+ if (loader == null) {
+ loader = ComponentsLoaderImpl.class.getClassLoader();
+ }
}
- }
- public Object transform(Object input) {
- if (null == input) {
- throw new NullPointerException(
- "Name for a UIComponent class to restore is null");
- }
- ClassLoader loader = getClassLoader();
- Class componentClass = null;
- try {
- componentClass = loader.loadClass(input.toString());
- } catch (ClassNotFoundException e) {
- throw new FacesException("Can't load class " + input.toString(), e);
- }
- return componentClass;
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.ajax4jsf.portlet.application.ComponentsLoader#createComponent(java
+ * .lang.String)
+ */
+ public UIComponent createComponent(String type) {
+ // Classes is a lazy Map, new object will be create on the fly.
+ Class<? extends UIComponent> componentClass = classes.get(type);
+ if(null == componentClass){
+ try {
+ componentClass = loader.loadClass(type).asSubclass(UIComponent.class);
+ classes.put(type, componentClass);
+ } catch (ClassNotFoundException e) {
+ throw new FacesException("Can't load class " + type, e);
+ }
- /**
- * lazy create ClassLoader instance.
- * @return
- */
- protected synchronized ClassLoader getClassLoader() {
- if (loader == null) {
- loader = Thread.currentThread().getContextClassLoader();
- if (loader == null) {
- loader = this.getClass().getClassLoader();
- }
-
+ }
+ try {
+ return componentClass.newInstance();
+ } catch (InstantiationException e) {
+ throw new FacesException(
+ "Error on create new instance of the component with class "
+ + type, e);
+ } catch (IllegalAccessException e) {
+ throw new FacesException(
+ "IllegalAccess on attempt to create new instance of the component with class
"
+ + type, e);
+ }
}
- return loader;
- }
}
Modified:
trunk/framework/impl/src/main/java/org/ajax4jsf/application/TreeStructureNode.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/application/TreeStructureNode.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/application/TreeStructureNode.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -24,6 +24,7 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -37,17 +38,17 @@
/**
* @author asmirnov
- *
+ *
*/
final class TreeStructureNode implements Externalizable {
/**
* TODO - implement Externalizable to reduce serialized state.
*/
- private static final long serialVersionUID = -9038742487716977911L;
+ private static final long serialVersionUID = -9038742487716977912L;
private static final String NULL_ID = "";
- private Map<String, TreeStructureNode> facets = null;
+ private List<FacetEntry> facets = null;
private List<TreeStructureNode> children = null;
@@ -68,27 +69,30 @@
+ clientId);
}
Map<String, UIComponent> componentFacets = component.getFacets();
- for (Iterator<Entry<String,UIComponent>> i =
componentFacets.entrySet().iterator(); i
- .hasNext();) {
- Entry<String,UIComponent> element = i.next();
+ for (Iterator<Entry<String, UIComponent>> i = componentFacets
+ .entrySet().iterator(); i.hasNext();) {
+ Entry<String, UIComponent> element = i.next();
UIComponent f = element.getValue();
if (!f.isTransient()) {
TreeStructureNode facet = new TreeStructureNode();
facet.apply(context, f, uniqueIds);
if (null == facets) {
- facets = new HashMap<String, TreeStructureNode>();
+ facets = new ArrayList<FacetEntry>(componentFacets.size());
}
- facets.put(element.getKey(), facet);
+ facets.add(new FacetEntry(element.getKey(), facet));
}
}
- for (Iterator<UIComponent> i = component.getChildren().iterator(); i.hasNext();)
{
+ List<UIComponent> componentChildren = component.getChildren();
+ for (Iterator<UIComponent> i = componentChildren.iterator(); i
+ .hasNext();) {
UIComponent child = i.next();
if (!child.isTransient()) {
TreeStructureNode t = new TreeStructureNode();
t.apply(context, child, uniqueIds);
if (null == children) {
- children = new ArrayList<TreeStructureNode>();
+ children = new ArrayList<TreeStructureNode>(
+ componentChildren.size());
}
children.add(t);
@@ -101,16 +105,16 @@
component = loader.createComponent(type);
component.setId(id);
if (null != facets) {
- for (Iterator<Entry<String, TreeStructureNode>> i =
facets.entrySet().iterator(); i.hasNext();) {
- Entry<String, TreeStructureNode> element = i.next();
- UIComponent facet = ( element.getValue())
- .restore(loader);
- component.getFacets().put(element.getKey(), facet);
+ for (Iterator<FacetEntry> i = facets.iterator(); i.hasNext();) {
+ FacetEntry element = i.next();
+ UIComponent facet = (element.getNode()).restore(loader);
+ component.getFacets().put(element.getName(), facet);
}
}
if (null != children) {
- for (Iterator<TreeStructureNode> i = children.iterator(); i.hasNext();) {
+ for (Iterator<TreeStructureNode> i = children.iterator(); i
+ .hasNext();) {
TreeStructureNode node = i.next();
UIComponent child = node.restore(loader);
component.getChildren().add(child);
@@ -120,37 +124,37 @@
return component;
}
- /**
- * @return the facets
- */
- public Map<String, TreeStructureNode> getFacets() {
- return facets;
- }
+ // /**
+ // * @return the facets
+ // */
+ // public List<FacetEntry> getFacets() {
+ // return facets;
+ // }
+ //
+ // /**
+ // * @param facets
+ // * the facets to set
+ // */
+ // public void setFacets(List<FacetEntry> facets) {
+ // this.facets = facets;
+ // }
+ //
+ // /**
+ // * @return the children
+ // */
+ // public List<TreeStructureNode> getChildren() {
+ // return children;
+ // }
+ //
+ // /**
+ // * @param children
+ // * the children to set
+ // */
+ // public void setChildren(List<TreeStructureNode> children) {
+ // this.children = children;
+ // }
/**
- * @param facets
- * the facets to set
- */
- public void setFacets(Map<String, TreeStructureNode> facets) {
- this.facets = facets;
- }
-
- /**
- * @return the children
- */
- public List<TreeStructureNode> getChildren() {
- return children;
- }
-
- /**
- * @param children
- * the children to set
- */
- public void setChildren(List<TreeStructureNode> children) {
- this.children = children;
- }
-
- /**
* @return the type
*/
public String getType() {
@@ -189,12 +193,12 @@
}
int facetsSize = in.readInt();
if (facetsSize > 0) {
- facets = new HashMap<String, TreeStructureNode>(facetsSize);
+ facets = new ArrayList<FacetEntry>(facetsSize);
for (int i = 0; i < facetsSize; i++) {
String facetName = in.readUTF();
TreeStructureNode facet = new TreeStructureNode();
facet.readExternal(in);
- facets.put(facetName, facet);
+ facets.add(new FacetEntry(facetName, facet));
}
}
int childrenSize = in.readInt();
@@ -213,10 +217,10 @@
out.writeUTF(null == id ? NULL_ID : id);
if (null != facets) {
out.writeInt(facets.size());
- for (Iterator<Map.Entry<String, TreeStructureNode>> i =
facets.entrySet().iterator(); i.hasNext();) {
- Map.Entry<String, TreeStructureNode> entry = i.next();
- out.writeUTF(entry.getKey());
- TreeStructureNode node = entry.getValue();
+ for (Iterator<FacetEntry> i = facets.iterator(); i.hasNext();) {
+ FacetEntry entry = i.next();
+ out.writeUTF(entry.getName());
+ TreeStructureNode node = entry.getNode();
node.writeExternal(out);
}
@@ -225,7 +229,8 @@
}
if (null != children) {
out.writeInt(children.size());
- for (Iterator<TreeStructureNode> i = children.iterator(); i.hasNext();) {
+ for (Iterator<TreeStructureNode> i = children.iterator(); i
+ .hasNext();) {
TreeStructureNode child = i.next();
child.writeExternal(out);
}
@@ -234,4 +239,40 @@
out.writeInt(0);
}
}
+
+ @SuppressWarnings("serial")
+ private static final class FacetEntry implements Externalizable {
+ private String name;
+ private TreeStructureNode node;
+
+ public String getName() {
+ return name;
+ }
+
+ public TreeStructureNode getNode() {
+ return node;
+ }
+
+ /**
+ * @param name
+ * @param node
+ */
+ public FacetEntry(String name, TreeStructureNode node) {
+ super();
+ this.name = name;
+ this.node = node;
+ }
+
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ this.name = in.readUTF();
+ this.node = new TreeStructureNode();
+ this.node.readExternal(in);
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeUTF(name);
+ node.writeExternal(out);
+ }
+ }
}
\ No newline at end of file
Modified:
trunk/framework/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
===================================================================
---
trunk/framework/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -43,7 +43,7 @@
}
};
- private static final int COUNT = 2000;
+ private static final int COUNT = 500;
private static final int PASS_COUNT = 2;
@@ -56,8 +56,13 @@
try {
for (int i = 0; i < COUNT; i++) {
+ try {
threads[i] = new LRUMapCacheTestThread(cache, new Integer(new
Random().nextInt(10)));
threads[i].start();
+ } catch (OutOfMemoryError e) {
+ System.out.println("Out of memory pass:"+k+" thread: "+i);
+ throw e;
+ }
}
} catch (Exception e) {
e.printStackTrace();
Modified: trunk/framework/jsf-test/pom.xml
===================================================================
--- trunk/framework/jsf-test/pom.xml 2009-01-06 02:13:37 UTC (rev 12127)
+++ trunk/framework/jsf-test/pom.xml 2009-01-06 02:38:39 UTC (rev 12128)
@@ -72,6 +72,10 @@
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
+ <!--
+ <exclusion> <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId> </exclusion>
+ -->
</exclusions>
</dependency>
<dependency>
Modified: trunk/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebResponse.java
===================================================================
---
trunk/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebResponse.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/jsf-test/src/main/java/org/richfaces/test/LocalWebResponse.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -179,7 +179,10 @@
headers.add(new NameValuePair(entry.getKey(), value));
}
}
- ;
+ int contentLength = serverConnection.getResponseContentLength();
+ if(contentLength>=0){
+ headers.add(new NameValuePair("Content-Length",
String.valueOf(contentLength)));
+ }
return headers;
}
}
\ No newline at end of file
Modified:
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingConnection.java
===================================================================
---
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingConnection.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingConnection.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -617,4 +617,8 @@
}
+ public int getResponseContentLength() {
+ return response.getContentLength();
+ }
+
}
Modified:
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingHttpResponse.java
===================================================================
---
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingHttpResponse.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingHttpResponse.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -46,6 +46,8 @@
private String contentType="text";
+ private int contentLength = Integer.MIN_VALUE;
+
private String encoding = StagingHttpRequest.UTF8;
@@ -397,8 +399,7 @@
* @see javax.servlet.ServletResponse#setContentLength(int)
*/
public void setContentLength(int len) {
- // TODO Auto-generated method stub
- log.info("unimplemented response method setContentLenght");
+ this.contentLength = len;
}
/*
@@ -442,6 +443,13 @@
}
/**
+ * @return the contentLength
+ */
+ int getContentLength() {
+ return contentLength;
+ }
+
+ /**
* @return the redirectLocation
*/
String getRedirectLocation() {
Modified:
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingServer.java
===================================================================
---
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingServer.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/jsf-test/src/main/java/org/richfaces/test/staging/StagingServer.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -13,6 +13,7 @@
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
@@ -96,6 +97,8 @@
private ThreadLocal<HttpSession> sessions = new ThreadLocal<HttpSession>();
+ private List<ServerHttpSession> sessionInstances = new
ArrayList<ServerHttpSession>();
+
private boolean sessionPerThread = false;
@@ -701,6 +704,7 @@
listener.sessionCreated(event);
}
});
+ sessionInstances.add(sessionImpl);
}
return httpSession;
}
@@ -762,8 +766,8 @@
this.initialised = false;
// Destroy session
// TODO - destroy all threads.
- HttpSession session = getCurrentSession();
- if (null != session) {
+ for (Iterator<ServerHttpSession> sessionIterator = sessionInstances.iterator();
sessionIterator.hasNext();) {
+ ServerHttpSession session = sessionIterator.next();
// inform session listeners.
final HttpSessionEvent event = new HttpSessionEvent(session);
fireEvent(SESSION_LISTENER_CLASS,
@@ -773,8 +777,9 @@
}
});
session.invalidate();
- setCurrentSession(null);
+ sessionIterator.remove();
}
+ setCurrentSession(null);
// Inform listeners
final ServletContextEvent event = new ServletContextEvent(context);
fireEvent(CONTEXT_LISTENER_CLASS,
Modified:
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ResourceServiceThreadsTestCase.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ResourceServiceThreadsTestCase.java 2009-01-06
02:13:37 UTC (rev 12127)
+++
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ResourceServiceThreadsTestCase.java 2009-01-06
02:38:39 UTC (rev 12128)
@@ -124,7 +124,7 @@
}
public void testTreadServiceResource() {
- TestCaseRunnable[] runnables = new TestCaseRunnable[1000];
+ TestCaseRunnable[] runnables = new TestCaseRunnable[200];
for (int i = 0; i < runnables.length; i++) {
runnables[i] = new ResourceRunner(String.valueOf(i % 10));