Performance Issues when Moving Multiple Shapes

Hi All,
We seem to be having choppy performance when selecting more than 10 or so objects and then moving them. Selecting one object is very responsive. We have looked at our bindings and optimized the makeTwoWay option to only those properties that need two way bindings. Could there be something else that we need to look at to improve performance.

It’s hard to say without knowing your app. Please review: http://gojs.net/latest/intro/performance.html

So I think I may have some insight to what is going on with our performance.

I believe the key lies in the undoManager. Our application is using the undoManager to record all changes to objects, and this may be the cause of the performance issues when too many objects get onto the canvas.

I see the same behavior with the State Chart example on the GoJS website. If I duplicate all the objects several times over and then select all objects and try to move I get the choppy performance.
http://gojs.net/latest/samples/stateChart.html

I do not see the same behavior with the Grid Layout example. I can duplicate the objects many times over and little to no choppy performance when moving all objects.
http://gojs.net/latest/samples/gLayout.html

The one key difference between both examples is the ability to undo and redo.

Any ideas?

It is more so the links and link template than it is the undo manager in this case. You can test by duplicating the objects many times, pressing Save, and then Load in the state chart sample (so that there is no undo history) and you’ll still see the issue.

However, if you delete the linkTempalte from the state chart sample, you’d see a measurable improvement in performance when there are a large number of nodes/links.

Man, you folks are fast :). Thanks Simon. I will continue to look into this. Perhaps we are doing something like this, I cannot tell.

I think I found the source of our performance issues. When we remove the makeTwoWay on the bindings below the performance problem goes away when we use the DraggingTool on multiple selected objects. But we lose the ability to keep track of the position and location in the data model when using the Dragging tool

new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
new go.Binding("position", "pos", go.Point.parse).makeTwoWay(go.Point.stringify)

So here is what I am trying to figure out.

How can I avoid the performance overhead of calculating all the posisition and location moves on each mouse move, while ensuring that I can keep my data model in sync with object the location and position properties of my graph objects so they will get persisted into my data model?

It seems to me that saving both the Node.location and the Node.position is wasteful. I suppose there might be situations where you might want to save them both, but I would hope you could avoid that.

The other thing is that you can save on the string conversions by not using those two static Point conversion functions. That would mean, though, that the model would have Point objects in them rather than strings. You’d have to adjust your model saving/loading code appropriately. If you are using Model.toJson and Model.fromJson, that’s OK because those methods handle instances of such classes, but the generated JSON would be noticeably larger and less readable.

Walter,

Thanks for getting back with me. I did a little experiment where I only bound to location, made it a twoWay without the string conversions, and I still get the same performance problem.

Is there a way before we save that we can force an update of the entire data model based on only the one way bindings that way we are sure that we save all the properties to the data model.

OneWay Bindings never update model data, so I don’t know what you want to do by “force an update of the entire data model”.

You can certainly execute whatever code you like before calling Model.toJson (or whatever you are doing to implement persistence).

Walter,

What I am trying to do is preserve the position and location into the data model after I have moved an object.

For example.

I put a triangle on the diagram. (I have a one way binding on the triangle location property. Use the OneWay to prevent the performance issue I described above.)
I move the triangle with DraggingTool.
I save the diagram.model and preserve the location of the triangle.

Also, I am open to solutions that can allow me to override the updating of the model during a mouse-move and only update it after the mouse-up event fires (when moving the object that is).

I was just saying that before you call Model.toJson, you could iterate through the Diagram.nodes and update their node.data.location property values.

Yes, you could do such manual updates of the Node.data properties in “SelectionMoved” and “SelectionCopied” DiagramEvent listeners.

The SelectionMoved DiagramEvent may work. I will give it try. Thanks Walter.