[
http://jira.jboss.com/jira/browse/RF-3569?page=comments#action_12415509 ]
martin bischoff commented on RF-3569:
-------------------------------------
over the last days i adapted the src of the tree and changed the html structure from
nested tables to ul-li constructs with a view to implement a relative complex styleguide.
as a result of this, the cpu time allocation measured by jprofiler changed. here is a
small comparision, maybe it helps you.
modified tree - ul
org.ajax4jsf.webapp.tidy.tidyparser.parsehtmlbytidy 86%:
|-org.ajax4jsf.org.wc3.tidy.tidy.parsedom 31%
|-org.ajax4jsf.org.wc3.tidy.tidy.pprint 23.5%
|-org.wc3.dom.nodelist.getlength 20%
|-org.wc3.dom.item 10%
org.ajax4jsf.application.ajaxviewhandler.renderview 7.8%
orgiginal tree - table
org.ajax4jsf.webapp.tidy.tidyparser.parsehtmlbytidy 90%:
|-org.ajax4jsf.org.wc3.tidy.tidy.parsedom 45%
|-org.ajax4jsf.org.wc3.tidy.tidy.pprint 34.5%
|-org.wc3.dom.nodelist.getlength 6.8%
|-org.wc3.dom.item 3.6%
org.ajax4jsf.application.ajaxviewhandler.renderview 7.6%
<rich:tree> possible performance issue
---------------------------------------
Key: RF-3569
URL:
http://jira.jboss.com/jira/browse/RF-3569
Project: RichFaces
Issue Type: Quality Risk
Affects Versions: 3.2.0
Reporter: martin bischoff
Assigned To: Nick Belaevski
Fix For: 3.2.2
i've got an quite simple tree with "just" 50 elements �¡ 200 childs ->
10.000 nodes
every node gots:
- some little text
- image for a checkbox via h:graphicImage
- a4j:support for listenersupport at the image
expanding/collapsing nodes and checking the checkboxes takes a lot of time...
jprofiler tells me that most of the time is spend by domparsing. i dont know if i handle
the tree as intended. here is some code:
JSP
[code]
<%@ taglib
uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib
uri="http://richfaces.org/rich" prefix="rich"%>
<%@ taglib
uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib
uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<head>
<title>tree</title>
</head>
<body>
<f:view>
<h:form>
<a4j:loadStyle src="/res/button.css" />
<a4j:loadStyle src="/res/tree/style.css" />
<a4j:commandButton id="show_me" value="show childs"
styleClass="normalButton">
<a4j:ajaxListener type="controller.listener.ListenerBean" />
</a4j:commandButton>
<h:panelGrid columns="2">
<h:outputLabel>
<h:outputText value="infinite Tree
extended"></h:outputText>
<rich:tree componentState="#{treeBean.treeState}"
id="infinite_Tree_expanded" style="width:300px"
switchType="ajax" stateAdvisor="#{treeDemoStateAdvisor}">
<rich:recursiveTreeNodesAdaptor roots="#{treeBean.rootNodes}"
var="item" nodes="#{item.children}">
<rich:treeNode
nodeSelectListener="#{treeBean.processSelection}">
<h:graphicImage value="/res/tree/chkb_#{item.state}.png">
<a4j:support event="onclick"
reRender="infinite_Tree_expanded"
actionListener="#{item.actionListener}"/>
</h:graphicImage>
<h:outputText value="#{item.value} - #{item.state}"/>
</rich:treeNode>
</rich:recursiveTreeNodesAdaptor>
</rich:tree>
</h:outputLabel>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>[/code]
TreeBean:
[code]package my_tree;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.faces.FacesException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import org.richfaces.component.state.TreeState;
import org.richfaces.event.NodeSelectedEvent;
public class TreeBean {
private TreeNode rootNode = null;
private TreeNode[] rootNodes = null;
private TreeState treeState;
private static final String DATA_PATH =
"/res/tree/simple-tree-data.properties";
public TreeNode getRootNode() {
if (rootNode == null) {
loadTree();
}
return rootNode;
}
public void setRootNode(TreeNode rootNode) {
this.rootNode = rootNode;
}
public TreeNode[] getRootNodes() {
if (rootNodes == null) {
rootNodes = this.getRootNode().getChildren();
}
return rootNodes;
}
public void setRootNodes(TreeNode[] rootNodes) {
this.rootNodes = rootNodes;
}
public TreeState getTreeState() {
return treeState;
}
public void setTreeState(TreeState treeState) {
this.treeState = treeState;
}
private void addNodes(String path, TreeNode node, Properties properties) {
boolean end = false;
int counter = 1;
while (!end) {
String key = path != null ? path + '.' + counter : String
.valueOf(counter);
String value = properties.getProperty(key);
if (value != null) {
TreeNode newNode = new TreeNode(value);
newNode.setParent(node);
node.addNode(newNode);
addNodes(key, newNode, properties);
counter++;
} else {
end = true;
}
}
}
private void loadTree() {
System.out.println("TreeBean -> loadTree()");
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
InputStream dataStream = externalContext.getResourceAsStream(DATA_PATH);
try {
Properties properties = new Properties();
properties.load(dataStream);
rootNode = new TreeNode("root");
addNodes(null, rootNode, properties);
// manual tree extension
TreeNode dummy = new TreeNode("Sichtlinie");
int count = 0;
for (int i = 1; i <= 50; i++) {
count++;
TreeNode node = new TreeNode("i" + i);
for (int j = 1; j <= 200; j++) {
count++;
if (count % 1000 == 0) {
System.out.println(count);
}
TreeNode child = new TreeNode("j" + j);
child.setParent(node);
node.addNode(child);
}
node.setParent(dummy);
dummy.addNode(node);
}
rootNode.addNode(dummy);
} catch (IOException e) {
e.printStackTrace();
throw new FacesException(e.getMessage(), e);
} finally {
if (dataStream != null) {
try {
dataStream.close();
} catch (IOException e) {
e.printStackTrace();
externalContext.log(e.getMessage(), e);
}
}
}
}
public void processSelection(NodeSelectedEvent arg0)
throws AbortProcessingException {
System.out.println("SimpleTreeBean -> processSelection fired by "
+ arg0.getComponent().getId());
}[/code]
TreeNode:
[code]package my_tree;
import javax.faces.event.ActionEvent;
import org.richfaces.model.TreeNodeImpl;
public class TreeNode{
private String value;
private String state;
private TreeNode parent;
private TreeNode[] children;
public TreeNode(String value) {
this.value = value;
this.state = "";
}
public synchronized void addNode(TreeNode newChild) {
System.out.println("addNode("+newChild.getValue()+")");
if (this.children == null) {
TreeNode[] merged = new TreeNode[1];
merged[0] = newChild;
this.children = merged;
} else {
TreeNode[] merged = new TreeNode[this.children.length + 1];
int i;
for (i = 0; i < this.children.length; i++) {
merged[i] = this.children[i];
}
merged[merged.length - 1] = newChild;
this.children = merged;
}
}
public synchronized void addNodes(TreeNode[] newChildren) {
System.out.println("addNodeS("+newChildren.length+")");
TreeNode[] merged = new TreeNode[newChildren.length
+ this.children.length];
int i;
for (i = 0; i <= this.children.length; i++) {
merged[i] = this.children[i];
}
for (int i2 = i; i2 <= newChildren.length + i; i2++) {
merged[i2] = newChildren[i2];
}
this.children = merged;
}
public synchronized void removeNodes(TreeNode[] removeChildren) {
TreeNode[] splitted = new TreeNode[this.children.length
- removeChildren.length];
int pos = 0;
for (int i = 0; i <= this.children.length; i++) {
boolean contains = false;
for (int j = 0; j <= removeChildren.length; j++) {
if (this.children[i] == removeChildren[j]) {
contains = true;
}
}
if (contains == false) {
splitted[pos] = this.children[i];
pos++;
}
}
}
public String checkSibling(){
//System.out.println("checkSibling() of "+this.value);
if(this.children!=null){
String state = null;
int checked = 0;
int sub = 0;
int i;
TreeNode[] siblings = this.children;
for (i = 0; i < siblings.length; i++) {
TreeNode treeNode = siblings[i];
//System.out.println("\t"+treeNode.getValue()+" -
"+treeNode.getState());
if(!treeNode.getState().equals("")){
if(treeNode.getState().equals("checked")){
checked++;
} else if(treeNode.getState().equals("sub")){
sub++;
}
}
}
if(checked == i){
state = "checked";
} else if(sub > 0 || checked > 0) {
state = "sub";
} else {
state = "";
}
//System.out.println("siblings: "+i+" (checked: "+checked+"
sub: "+sub+") -> "+state);
return state;
} else {
return "";
}
}
public void setChildsChecked(TreeNode node){
//System.out.println("TreeNode -> setChildsChecked of "+node.getValue());
if(node.getChildren()!=null){
TreeNode[] children = node.getChildren();
for (int i = 0; i < children.length; i++) {
TreeNode treeNode = children[i];
treeNode.setState("checked");
setChildsChecked(treeNode);
}
}
}
public void setChildsUnchecked(TreeNode node){
//System.out.println("TreeNode -> setChildsUnchecked of
"+node.getValue());
if(node.getChildren()!=null){
TreeNode[] children = node.getChildren();
for (int i = 0; i < children.length; i++) {
TreeNode treeNode = children[i];
treeNode.setState("");
setChildsUnchecked(treeNode);
}
}
}
public void setParentsState(TreeNode node){
System.out.println("TreeNode -> setParentsState of "+node.getValue());
node.setState(node.checkSibling());
if(node.getParent()!=null){
setParentsState(node.getParent());
}
}
public void actionListener(ActionEvent ae){
//System.out.println("TreeNode -> nodeListener fired by
"+ae.getComponent().getId());
if(this.state == "checked"){
this.state = "";
setChildsUnchecked(this);
} else {
this.state = "checked";
setChildsChecked(this);
}
if(this.parent!=null){
setParentsState(this.parent);
}
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public TreeNode[] getChildren() {
return children;
}
public void setChildren(TreeNode[] children) {
this.children = children;
}
public TreeNode getParent() {
if(parent==null){
return null;
} else {
return parent;
}
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
[/code]
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira