I was trying to troubleshoot why a few of our projects have terrible performance in the Designer for some of our screens. The issue seemed to be limited to MacOS (video below) - although we didn't test Linux. The same windows have no performance issues when opened in the Designer running on Windows OS. After a lot of trial and error I tracked it down to the gradient fill paints in the equipment objects that seem to be the culprit. When I set them to a solid color, the performance goes back to what I would expect. The other interesting aspect here is that the same window works fine in a client running on MacOS - it is completely limited to the Designer.
I generated a quick example to show the performance hit with and without gradients. I went a little overboard with the number of objects to show how severe it is, but honestly the number of paths I have in there isn't that far off from many of the symbol factory objects - especially if you have 20 plus symbol factory components in the same window. I've replicated this same behavior in versions 8.0.x, 8.1.25, and 8.1.28. I do NOT have the same issue with a 7.9.x gateway even though many of the project windows on that gateway have more gradients than the windows in the 8.x projects. I have replicated this behavior on a couple versions of MacOS (13.4.1(c), I don't have the other one handy...). They are both ARM based Macs. Attached a bare-bones Vision window if interested.
Wouldn't you expect the performance to be terrible in the Designer and Client, not just the Designer? I'm wayyyy out of my wheelhouse here so I'm honestly curious!
Yeah, that’s my first instinct. But there’s other stuff on the screen with the Designer, who knows what kind of weird rendering dependencies might be at play.
I thought it might be an interesting one since it only impacts the Designer!
...yea...to the point where I won't even work on the screens. Have the others on the team who are using Windows machines take care of them. Good kick in the butt though to start transitioning those screens to High Performance HMI designs
Well, I broke the XCode profiler. Specifically enabling Metal definitely helped, but was still not usable. But I can't say for sure it was even running or not without peeking at the trace. I'll have to pick this up another time.
Haha, I knew you were going to have that response - too easy! The less I touch that pile of Windows laptop I have, the happier I am! And I used to only use Windows. Maybe some day I'll smarten up and switch to Linux, but probably not
Alright, well, XCode finally finished thinking at some point last night, so I can confirm that performance is still miserable (in the Designer) on Java 17 with the Metal backend. It's definitely a clue that the client is fine, but like Kevin said, there's a ton of code in the Designer to make the "WYSIWYG" stuff work, so it could be breaking down anywhere in there, and I've already spent enough time out of band.
I will file a ticket to investigate further. If it were awful in the client too, I'd throw it out as a JDK bug, but that it's limited to the designer really does point to us doing something "wrong" that just ends up catastrophic on MacOS, for whatever reason.
Threw together a quick and dirty script to search for gradient paint properties in a window to speed up getting rid of them. We may eventually have it actually replace the color but for now we want to do this by hand.
If anyone can think of something I'm missing with this script, I'd love to hear it!
from com.inductiveautomation.factorypmi.application.components.template import VisionTemplate
from com.inductiveautomation.ignition.client.util.gui import paints
def recursive_gradient_search(comp, gradients, path="", template_name=None):
path = "{}/{}".format(path, comp.name)
for obj in comp.getComponents():
# Iterate through objects that contain other objects.
if hasattr(obj, "getComponents"):
if isinstance(obj, VisionTemplate):
template_name, path = obj.name, ""
recursive_gradient_search(obj, gradients, path, template_name)
# Find object properties that have gradient data types
root_type = "Window" if template_name is None else "Template"
print_strings = ["{} Path: {}/{}".format(root_type, path, obj.name)]
for el in dir(obj):
try:
if isinstance(getattr(obj, el), gradients):
print_strings.append(" Property Name: {}".format(el))
except:
# Many legitimate reasons the try can fail.
pass
if len(print_strings) > 1:
print "\n".join(print_strings)
print "Search for Object Properties with Gradient Paints\n"
gradients = (
paints.LinearGradientPaint,
paints.MultipleGradientPaint,
paints.RadialGradientPaint,
paints.RelativeLinearGradientPaint,
paints.RelativeRadialGradientPaint
)
recursive_gradient_search(event.source.parent, gradients)
Note: I know that this will not catch objects that may have a script or binding on them to set a gradient based on certain conditions...luckily this isn't something we've used, so I'm not worried about it.