-
Notifications
You must be signed in to change notification settings - Fork 434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug]: OPM memory leak #1935
Comments
The OPM module hasn't seen any serious contribution for many years. This is due to the fact, that the person who built it, no longer is active in the project. As far as I know, there isn't anyone else really deeply involved in this. I think I was the only one occasionally working on it. However have I stopped contributing to the project for free ... I would be willing to have a look at this and your other issue, for a donation of at least 60€ to my BuyMeACoffee page https://buymeacoffee.com/christoferu |
Ok ... running it for longer shows the problem: However from how I look at the code I think calling read repeatedly seems not quite the design-pattern the initial creator had in mind. It looks as if it was intended to re-use the entity and refresh it. Right now for every call, ByteBuddy creates a new class instance, which is filling up the memory. I assume there's not much that I can do to fix that. However I most probably will be able to figure out how the initial author was planning to use the OPM (And update the documentation). I do see code that is meant for updating the entity properties ... just not sure how to use it ;-) In that case you would only create one instance of the Entity and that would prevent the class memory from filling up. |
Ok ... so I think I've solved the mystery ... You were using the OPM the wrong way. However I don't blame you, I intuitively would have done it the same way. It seems that If you however call So if I change your code to the following code, I no longer see the memory usage increase:
I am currently updating the documentation on the OPM. |
I also updated the entity manager code a bit and now, by adding this method to your FooRxEntity class:
You can trigger an update of all properties of the entity. I would reccomend you add that method to your entity, then you add a sensible cacheDurationMillis value to each @PlcTag annotation. Then instead of calling "entityManager.read" you do the "connect" and in your look you simply call "entity.updateAllTheTags()" to force a bulk read. If all goes right, you should be utilizing the new modbus optimizer to do a lot more efficient bulk reads and then you simply use the entity. So I just pushed my changes ... there's one code-change needed to make the "updateAllTheTags" thing work, so be sure to pull the latest changes. I hope I was able to help solve your problem? If not, ping me and I'll do my best to help. |
But admittedly I would strongly encourage you to not use the OPM path if you want to fetch many fields repeatedly. Using the PlcConnectionCache (https://plc4x.apache.org/plc4x/latest/users/tools/connection-cache.html) in combination with the normal PLC4X Read API (https://plc4x.apache.org/plc4x/latest/users/getting-started/plc4j.html) I personally never considered the OPM more than a proof of concept and considering that nobody else seems to have been able to help you and that there's nobody else maintaining this part of the project ... and considering that I personally would probably rather drop the component because cleaning it up and making it a stable solution, would require almost a complete re-write. I still hope I was able to provide a solution to your problem. |
Ok ... took a bit longer than expected ... but the updated documentation should be available here: https://plc4x.apache.org/plc4x/pre-release/users/tools/opm.html |
Thanks a lot for the effort. The intention was to pass the disconnected entity forward, that's why we used @chrisdutz I think there is a typo in the new documentation. In the Simple Example (Detached) code snippet, it should be |
Oh yeah ... thanks for spotting that .... should be fixed in a few minutes as soon as the site-build is through. I think having a connected entity, cloning that and passing it along can cause really odd problems. I would really strongly encourage you not to do the first and still not do to the second option. Why don't you simply do a read operation via the PlcConnectionCache and assemble a Pojo from the results and then pass that around? I'd be happy to provide you with an example, if you give me a bit more detailed example (can send me via email directly, if you don't want to share publically) Chris |
My idea was to obtain a detached copy by cloning the connected entity to avoid further PLC queries. But as said, I will switch to the Read API completely. Either by assembling the entity or directly passing the |
I do think a connected entity always calls the PLC on every access to the property (unless the cache setting tells it to use the cached version). So yeah ... please do a regular PlcReadRequest ... you'll have a lot less problems ;-) |
What happened?
Production use case:
Issue:
Comparing dumps (from production) show an increase of byte[] objects like:
java.lang.String#45053 : FooRxEntity$ByteBuddy$opFq0T9M$auxiliary$5LGzfXOE
.The ByteBuddy instances are created here:
org.apache.plc4x.java.opm.PlcEntityManager#connect(java.lang.Class<T>, java.lang.String, T)
therefore I think that PlcEntityManager is responsible for the leak.
Code to reproduce the issue:
And the entity:
The test is started with VM options

-Xms128m -Xmx128m
. After ~4 minutes OOM is thrown.I can reproduce the OOE with a real connection. This take a lot more time because the plc support a max reading rate of ~300ms.
Real test:
Mock dump:
heapdump-1733998935197.zip
Production dump:
heapdump-1732691913936.zip
Please let me know if you need more details and thank you in advance.
Version
v0.12.0
Programming Languages
Protocols
The text was updated successfully, but these errors were encountered: