Hello, thanks for the measurements. I know what is happening.
What is taking the most time (2.5 seconds) are basically process context switches and data marshalling between your application and EasyOPC process. This happens every time you access objects from EasyOPC. For example, obtaining a properly-typed interface from a VARIANT, accessing a property (such as Exception or Vtq or Value) etc. There is nothing wrong with your code - it was our conscious decision to design the interfaces in this way. In COM automation, about the only more effective way would be to return directly arrays of the actual things you need, so that would make an array of values, array of timestamps, array of qualities, array of error codes, array of message texts etc. That is possible but gives a terribly looking code.
Fortunately, you can eliminate the above process context switches by using to in-process EasyOPC. To do so, open the EasyOPC Options Utility, and on the System Parameters tab, uncheck "Local server" and check "In-process server".
The downside of the in-process component is that in some environments and situations, it is difficult to achieve a shutdown that is properly coordinated with the host. Hopefully, since you are in C++, this should not be a blocking problem.
Regards