Visibility Animation causing very slow client

I have several animations on a window, using a Timer and Visibility bindings. Initially I had a rotating widget that I changed the angle on with the timer value. Timer runs 0-9, and the expression changed the angle by Timer.Value*36. Because of all the bugs and problems with wandering widgets and dynamic rotation not maintaining centers I had to abandon this. So, I created 10 static images, each with a different angle, and linked each one with a visibility of the Timer.Value = x. Grouped the images on top of each other.

The timer is set to 500ms, but the actual time itā€™s incrementing is much slower. And Iā€™ve now noticed that all the animations are slow, the navigation is slow, and I see the circle busy element on most any operation. This is a very minimal application that Iā€™ve just started. Only about 300 tags used. Using the angle rotation method, the response was fast.

I am doing this development and testing across the customerā€™s VPN, so could it be a screen refresh issue? Or is there a limitation within Ignition about using a number of visibility animations? Thereā€™s 10 to 15 of these grouped stacks on a window.

Sounds like you are doing gateway calls (tags, db, etc) in the foreground thread. Donā€™t do this. Use asynchronous bindings for such things, and react to the propertyChange when the value arrives. Cache your images. Donā€™t go to the gateway to get them at every step. Use project script modules with top level dictionaries to hold your cached objects.

I have no idea what you just said, LOLā€¦Sorry, new to Ignition and not yet clear on all the terminologies. If there is a document/help area to read that you could point me to, that would be helpful.

Iā€™ll explain better. I have 10 widgets in a group. Each widget in the group has a visibility based on a local timer component in that window. I would assume that timer is local to the client and there is no need for any Gateway traffic. The entire group has its visible property binded to an OPC tag. If I put 15 of these groups on a window, the animations come to a grinding halt. As soon as I delete them, everything goes back to normal. But to me that should only be 15 tags that are being monitored, so no heavy lifting at all.

Now, I just realized that in those 10 widget visible bindings (inside the group) I also added the System tags (({[System]Client/System/SystemFlags} & 1 ) && !({[System]Client/System/SystemFlags} & 2)
so that the widgets donā€™t disappear in development mode. Could that possibly be the culprit? Again, I apologize for not being up to speed on what is and isnā€™t Gateway traffic.

So, a little more testing.

I removed any reference to any tags. All Iā€™m using is a local timer component on the window that times from 0 to 9. 10 widgets with visibility bound to timer.value=0, 1, 2, etc. Stack these widgets (center H/V), group them and it shows a turning wheel. As soon as I add more than 5 instances of this widget to a blank window with the timer, the timer and screen start to slow down. Go to 10 instances, and itā€™s severely hampered and unusable.

So to reiterate, no Tagsā€¦just using the timer property value bound to the visible property of each widget within a group.

Is this Vision or Perspective? If Perspective, all scripting is on the gateway, and traffic will matter.

When Phil said donā€™t use tags in the foreground thread, he meant donā€™t use the Tag() expression function and instead bind any tags you need to custom properties with tag or indirect tag bindings. You should use the same for all of your project

No, not just that. Don't use scripts in the foreground to read tags, either.

Vision only.

Iā€™ve used custom properties and bindings for indirectsā€¦on a pop-up for example. But in this case its an image widget. I have 10 individual images. Each one I click on, goto expression, enter property of timer.value=x where x is 0 to 9 for the 10 widgets. I then geoup these 10 together in one stack. Thats it. If I put 5 of these on an empty screen the timer starts to slow down. Granted thatā€™s 50 images with a visibility binding tied to property timer.value. But why would that slow everything down. In this test, no tags are used.

Ah, got itā€¦im not using the tag function or referencing them in scriptsā€¦always via binding.

I going to guess your widget isnā€™t smart enough to cache the image and is getting it from the gateway every time it becomes visible. Youā€™ll have to use another technique. Iā€™d use the paintable canvas.

3rd time the charmā€¦i only used this method because of the issues with rotation wandering and losing its center reference. Showing a turning image shouldnā€™t be so challenging:)

Well, hang on. Are you able to post a project export, or at least the window + images youā€™re using?
Something about this seems very fishy - you should have absolutely no performance issues from toggling component visibility.

Yes sir, I can export the test window with 10 of them showing the slowdown. Ill do so later tonight or in the morning. Ill try to take a video too if that helps.

Rotating Widget.zip (195.7 KB)

Attached is the exported window

Video of 4 widgets, fast movement

Video of 12 widgets, slower

Oof. Okay, so, I can tell you what the problem is, but thereā€™s no great fix.
So, the problem isnā€™t toggling the visibility - the problem is the fact that each of your animation ā€˜framesā€™ is angled - that means each time itā€™s drawn, Java Swing (Visionā€™s underlying rendering layer) has to render the image, then rotate it X degrees - and because Swing is both old and takes great pains to be cross-compatible, it does that rotation entirely on the CPU (thereā€™s no ā€œhardware accelerationā€, if youā€™re familiar with the term). So each group you create is just that many more rotation operations to perform, and Swing is going to do them all on the main GUI thread, which increases ā€˜perceivedā€™ slowdown.

So, what can you do?
Probably the easiest thing would be to manually ā€œcacheā€ the rotations - you could recreate the graphic you want in a tool like Inkscape, then export pre-rotated SVG or PNG images to use for your individual component frames.
Or, you could also start with the original graphic from Symbol Factory, at a reasonable size, on a blank window. Then rotate it through as many frames as you want, taking a screen capture/using system.print.printToImage for each.
As an alternative to toggling visibility on a bunch of individual components, you could also then upload them all to image management, and just use an Image component with a dynamic path (bound to a timer/signal generator) for each frame.

For another option, you could pack those frames into a .gif directly - you wonā€™t have dynamic control over the speed, but itā€™s guaranteed to have constant performance. You could toggle between a static graphic and the .gif if you want to show running/halted.

For yet another option, use a Paintable Canvas as Phil suggested - youā€™ll have ultimate control over the presentation, but itā€™s a steep learning curve.

1 Like

Thank you for the detailed response. Probably easiest and most straightforward is I can easily modify the original image in a 3rd party editor and paste them back. I could do it from Symbol Factory direct, but the properties for SF donā€™t seem to be exposed. Symbol Factory has properties like angle, size, color, etc. that Iā€™ve used in the past on other SCADA, but I donā€™t see them within ignition.

Anyway, at least I know the direction I need to head. Thanks!!

1 Like

Have you tried just binding the angle property of the symbol to the timer?
I just tested this on 7.9.16 using a symbol factory gear and a timer.
Set the timer to 500 ms Delay, step 10, Bound 360
Then I bound the gears angles to the timer value.
I have 30 of them on a vision window with no slowdown.