Extjs improve performance of treenode.appendchild() - extjs

I am using Extjs 4.2.1. I have a bufferedrenderer tree grid, where the requirement is to append many children to specific node.
Here is my code
Ext.suspendLayouts();
Ext.getCmp('bufferedTree').getStore().suspendEvents();
for(var i=0;i<node.length;i++){
node1.appendChild(node[i]);
nodesArray.push(node[i]);
}
node1.appendChild(nodesArray);
Ext.resumeLayouts(true);
Ext.getCmp('bufferedTree').getStore().resumeEvents();
node is selected nodes to append
node1 is parent to which nodes to be appended.
Its working fine, but the problem is when number of nodes to append increases, time required to appendchild increases.
Any solution to reduce time?

Each node addition is going to trigger a layout update, which is going to have a cost with performance. So the more you append, the greater the cost.
If you look at the docs for appendChild(), you'll notice that you can append either a single node, or an array of nodes. Instead of appending at each iteration of the loop, I would create an array of all the nodes you want to append, and then append them as one call. That way, the layout updates will only happen once, instead of once per node addition. This will almost certainly improve the performance.

Related

ReactJS sortable dnd tree setup

React newbie again.
I have and admin page for a forum. It's a tree structure with potentially infinite depth, ordered by order_id field.
I can get it from the api either as a tree (with a children array field holding the children of each node) or as a flat array with an ancestry (a string that holds the whole path to the node, separated by a /) and a parent_id field.
I need to be able to move them around, expand and collapse subtrees and be able to add a node in any place.
Now I have several questions:
Is there a good out-of-the-box UI library to be able to drag-drop them to rearrange? I found this one: https://github.com/frontend-collective/react-sortable-tree but I can't get it to not have a limited height frame, and also customizing those themes looks too complicated.
If I am to do it from scratch using react-dnd, what is the more efficient way of working with this tree - have it as a tree (how do I add/update the nodes?) or store it flat and build the tree on render (easy to manage the collection, but complicates rendering and sorting logic).
This sounds like a complicated and interesting problem. If the library cannot do what you want it to stylistically then you will have to build it from scratch.
I would store all of your node objects in an Array with a children property that holds a reference to all of it's children; you could use their order_id as a reference if it is guaranteed to be unique.
I would also store the parent node's order_id as well, as it will help when you manipulate the tree.
Nodes = [
{order_id: 1, name:"order1", children_ids:[2,3], parent_id: 0},
{order_id: 2, name:"order2", children_ids:[], parent_id: 1},
{order_id: 3, name:"order3", children_ids:[], parent_id: 1},
]
You will have to build the tree on render, it may be a brain twister but it's more than doable with a bit of work.
When you add a new node, you will have to update the parent and children of it's new spot in the tree.
When you rearrange a node, you will have to travel up to the parent and remove it from it's children. You will also have to travel down to it's children and set their parents to the rearranged node's old parent. This removes the node from the tree. Then, add the rearranged node to the tree.
Any manipulation you do will involve manipulating the parent and children of that node - this is why I recommend storing both children's id and the parent's id. It saves you from having to do too many tree traversals which is not computationally efficient.
I don't recommend using an ancestry field as you mentioned. The logic for moving nodes around will be too complicated and you would have to traverse and edit potentially the entire tree if you do it this way.
The first step is to integrate with react-dnd; make each node draggable. When you drop it onto another node to rearrange, you trigger your rearrange handler.
Best of luck.

AngularJS - Infinte Loop over a finite array

I have a list of anything from 10-500 records appearing on screen as a graphical array using standard NG-REPEAT, visualisation is a row of photographs
What I would like to achieve, but cant quite get my head around if its even possible is this...
A 'window' on screen that will only show 10 records - Done
You can scroll left or right through the entire list - Done
HOWEVER
What i would LIKE to achieve is that when the end of the list is reached, the list starts again from the beginning but in an infinite style loop. Both directions
I have never done anything like this and not quite sure how I would achieve this of my ng-repeat (item in ListofItems)
So I assume that the best solution is
when the user gets 40 records through 100 records, i push() the first 20 records from my $scope.ListofItems to the end of the array, and remove the equivalent first 20 records from the front.. this keeps a constant list of 100 records, no massive memory usage.. i can even do this on an individual record basis.. remove one record from end or beginning and add at the beginning or end of the list.
The user experience is an infinite scroll, but I suspect the browser experience could be slow and stuttering due to the processing going on
Push(), Pull(), Tracking and indexing would play a part but any suggestions would be appreciated whether this is even technically possible
EDIT : After some research. maybe
$scope.ListofItems.push($scope.ListofItems.shift());
could be a solution to move beginning to end, but not sure how to trigger this or go the other way (pull?)
EDIT2 : Just did a manually called function for the above and it shifts front item to end of list, though i would have no clue how to read the screen position to know when to fire the function
Going the other way around could be
$scope.ListofItems.unshift($scope.ListofItems.pop());
As a side note, I think it's important to keep in mind for large arrays that shift() and unshift() naturally cause a full reindexing and have a time complexity of O(n) where n is the length of the array, as opposed to push() and pop() which have a time complexity of O(1)

hierarchical pathfinding implementation

I want to divide my map in clusters and implement HPA*. Where do I start, each time I try this I run into problems. I need to implement this on a random and dynamically changing map.
I am unsure how to write an algorithm that places these "nodes", to connect the parts, in between sections/clusters of the map and update them. I guess every time open tiles lie in between closed tiles on the edge of a cluster/section there should be a node since inside the cluster it could be that multiple openings into the cluster do not connect to each other within this section.
Normally I would just have a big Tile[,] map. I guess I could just leave this be and create a cluster/section class that holds all the paths and nodes. And have a node class/struct that holds the 2 tiles that are connected between sections. I have read several articles about HPA* but I just can not wrap my head around implementing this correctly on a random and dynamical map. I hope to get some good pointers here although the question is not very clear.
-edit-
What i am trying to do is making cluster class that holds 10x10 tiles/nodes with on each side an entry point (several if there is a obstruction on the edge). The entries link to the next cluster.

Rush hour - Iterative Deepening

I have to solve the "rush hour puzzle" by iterative deepening algorithm. I have read a lot of topics here on stackoverflow and also on the internet. I think that I understand the iterative deepening algorithm. Basically you just go deeper into the tree and try to find the solution.
I figured that I need to create a graph or a tree from the puzzle, but I really don't have an idea how. Also, if I would have the tree, then how would I tell if something is a valid move or a final state?
There were answers that the nodes should be possible moves and the edges are between the nodes that can be reached in one move. I can imagine this, but somehow I'm getting trouble in see how this can be useful or better yet how can this solve the problem.
Please help me, I'm not asking for complete solution or code sample, I just need some easy explanation of the problem.
There is a reason you need to use the deepening algorithm. Imagine you name each car A, B, C, D... The root node of your tree is the initial board state. Now, move car A. You go down one node in the tree. Move car A back. You are at the initial state, but you made two moves to get here, so you are two nodes down the tree. Repeat over and over. You will never hit a final state.
The root node of your tree is the initial board state. Given that node, add a child node to it for every possible valid move. So, each child node will be what the initial tree looks like after one move. Now, for each of those child nodes, do the same thing: make a child node where each node is one move off the original child node.
Eventually, you will hit a solution to the puzzle. When that happens, you print the moves from the root node to the solution child node and quit. This algorithm ensures that you find a solution with the least number of moves.

Winform treeview sorted property is slow

I have a winforms TreeView control with the Sorted property set to true. I also override the default sorter by assigning and instance of IComparer to the TreeViewNodeSorter property.
Unfortunately adding a few thousand nodes using the AddRange function takes perhaps 10 seconds. If I set Sorted to false the AddRange function is < 1/2 second. (please no discussions about the validity of adding so many nodes)
Aha I hear you say.. there is a problem in my IComparer object. Not according to the profiler. Barely any time is spent in the sorting object and yet the AddRange function is right at the top of the list of slow functions.
The problem is easy to replicate in a test project. Simply create a list of TreeNodes and add it to the an existing expanded tree node using the AddRange function. This will use the default sort on the tree text - again it is disproportionately slow.
To demonstrate how disproportionately slow it is if I disable the Sorted property in the test probject and use the List<T>.Sort function (with a delegate that compares the Text of the nodes) on my list of nodes before adding them to the tree there is virtually no delay.
This leads to the workaround of sorting the nodes manually before using AddRange. That's OK but it means a lot of work to find the correct insertion point when adding nodes to an existing set of child nodes - rather less convenient than simply setting Sorted to true.
Is there anyway to speed up the behaviour?
EDIT - it seems the only way is to sort before adding.. it's a bit of a hassle but I came up with the following extension method:
public static void AddSortedRange(this TreeNodeCollection existingNodes, IList<TreeNode> nodes, TreeView treeView, IComparer sorter)
{
TreeNode[] array = new TreeNode[nodes.Count + existingNodes.Count];
existingNodes.CopyTo(array, 0);
nodes.CopyTo(array, existingNodes.Count);
Array.Sort(array, sorter);
treeView.BeginUpdate();
existingNodes.Clear();
existingNodes.AddRange(array);
treeView.EndUpdate();
}
It is quicker to copy the existing nodes to an array, append the new nodes, sort the array and then replace that trying to manipulate nodes inline in the tree view - the slowest operation in the above code is the existingNodes.Clear() call
The performance problems you have are related to the fact that you are adding items to a sorted TreeView. What happens behind the scenes when you add to a sorted list is that for each item that you are adding, it tries to find it's place, which means that it needs to go through the whole list for each item, now imagine how many iteration that makes for each new item :)
What you can do is this:
TreeView tv = new TreeView(); // Just so I have a TreeView variable
TreeNode[] nodes = ... // Well, your list of nodes that you want to add
tv.SuspendLayout();
tv.Sorted = false;
tv.Nodes.Clear();
tv.Nodes.AddRange( nodes );
tv.Sorted = true;
tv.ResumeLayout();
For performance reasons we are using the SuspendLayout/ResumeLayout methods to disable the painting process used by the TreeView when manipulating it's items, which we would cause by removing the items and then adding them as well, since it would need to repaint to add the new item that you are adding (for each of the items).
Right before we are doing any changes to the Nodes Collection we have to call Sorted = false; to disable the sorting (this is just temporary - the user will not see any changes because of SuspendLayout).
Then just add the items to the collection (since the TreeView is not sorted for the time being it should be really quick).
Then we enable the sorting again by calling Sorted = true; setting the Sorted Property to true will cause for the collection to do a sort.
This way, the sort will be performed only once (and therefore the TreeView will just go once through the items).
One more thing, if you have a custom sorter defined for the ListView (tv.ListViewItemSorter), set it to null before adding the items as well, just temporary of course, re-enable it again before the ResumeLayout call.
I experienced a locking situation using the Sort() method.
It worked fine for weeks, then once, it stucks, stucking my application with 25% CPU in the task manager.
var allTags = _TagEngine.GetTags(1, force);
try
{
TagTree.BeginUpdate();
TagTree.Nodes.Clear();
foreach (var rec in allTags)
{
... adding nodes in the tree
}
TagTree.Sort(); // <= stuck here !
}
finally
{
TagTree.EndUpdate();
}
So I watch inside the Sort() method using a decompiler, and I noticed it handles already the BeginUpdate/EndUpdate feature internally.
Then I moved the TagTree.Sort() outside the BeginUpdate/EndUpdate, and it works fine since.
var allTags = _TagEngine.GetTags(1, force);
try
{
TagTree.BeginUpdate();
TagTree.Nodes.Clear();
foreach (var rec in allTags)
{
... adding nodes in the tree
}
}
finally
{
TagTree.EndUpdate();
}
TagTree.Sort();
I hardly understood what happened here. Why it worked in the past, and suddenly stoped. Frankly, I did not had time enough to dig further and anyway, the most important is here : it works again.
I made a simple extension to the TreeView control. It is very fast. It moves internal storage to a Dictionary which makes a huge difference. In my real world example I have 100000 records that I need to load. It took 37 minutes before, but now it takes 2.2 seconds!!
You can find example and code on CodeProject: http://www.codeproject.com/Articles/679563/Fast-TreeView

Resources