There's quite a bit of OPC UA bashing across this project. So let me chime in to keep the "balance in the universe". OPC UA is a protocol to interact with an object-oriented information model. Basically CORBA done right to use object-oriented principles and reuse software components in industrial automation. Since OPC UA is a protocol, its performance depends mostly on the implementation. Some PLCs may be crappy. But…
I think the biggest issue I encountered with OPC-UA is the rather random nature of implementations from vendors.
For example, I had S7-1500 PLC deployed on a project, and we used OPC-UA to talk to it as well as to expose internals of the program that was talking to it.
We also had WinCC HMI, and while it could do basic read-write access to OPC-UA, we couldn't attempt to go for Method Calls, which would have considerably simplified a bunch of things for us.
Meanwhile, FreeOPC-UA (python) turned out to be a bit buggy ;)
It's a quite nice system, and I really like the object-oriented nature of it and support for modeling instead of random soup of PLC tags that appears to be the norm. Standard industry models for various components help extra there.
Currently I'm looking into implementing a wrapper around open62541 for Common Lisp and Ada, and possibly a CORBA & DDS translator for it. Originally I missed PLC4X completely, and we needed to talk to S7-1500 as soon as possible and kinda got stuck with Python, now I wish I could do it in Lisp or Ada and get it done probably much faster :)