I am working on an application that will start memory intensive operations at regular time intervals on a set of objects given by the user.
If the user gives us more than we can work with, we will eventually run out of memory and cause a JVM error.
We have tried skipping a time interval based on the amount of available memory. The problem is that there doesn't seem to be a reliable way to find the amount of available memory. Even if the user requests a small number of objects, the amount of memory used by the JVM will steadily increase until we start skipping time intervals. We will stop skipping once garbage collection runs, because the memory isn't *used*, it is just garbage memory. Unfortunately, telling the garbage collection to run right before testing the amount of available memory doesn't help as invoking garbage collection seems more like a suggestion to the JVM than an actual function.
Therefore, the effort to dynamically limit the set of objects seems to result in skipping time intervals needlessly. The other way to approach the issue is to proactively limit the number of objects that can be given by estimating how much memory those objects will cause to be taken up during execution of the memory intensive operations. The problem with this solution is obviously the estimation of how much memory will be used is difficult and error-prone (causing either overly-limiting the user or mistakenly allowing too many objects resulting in a crash).
Is there any way to determine the memory available dynamically without causing occasional needless skips?
The problem with JConsole and Visual VM is that it will give a good idea of what the memory footprint looks like in the internal environment with the set of objects populated in a certain way. These solutions are not possible as part of the actual executing code. Essentially, I am looking for something that can decide at runtime that the user has given too many objects, and truncate the set to only deal with what we can without running out of memory.
The Runtime.freeMemory method is what I meant when I said, "We have tried skipping a time interval based on the amount of available memory," as well as a management bean solution which seems to simply give the same results as Runtime.freeMemory. The problem with these is that they can vastly underestimate the free memory (and often do) because garbage collection hasn't yet removed the 'garbage' portion of the used memory yet.
Wondering if there is a way to avoid the out of memory error without attempting to predict the memory usage before starting.
It looks to me like the problem is with the amount of memory being produced by the application and the fact that it is not predictable. The tools here can just help report the problem. As far as memory load predictions go, it is entirely up to your application to dictate the terms. Some trial and error load tests can help you determine some sort of pattern. If you ensure that the same VM, memory, clusters etc etc are duplicated in QA then you might be able to track it.
Is it possible to queue these requests. Can you use JMS to send messages to a queue and have a client process them one at a time ?
Mazer Lao Tzu
Joined: Jan 20, 2010
Processing them one at a time is not possible because it vastly reduces the amount of work we can accomplish within a time interval.
Just to be clear, the application is expected to be a memory hog. We are not running out of memory because of a memory leak--we are running out of memory because we actually run out of memory.
Thanks for you suggestions, sorry I cannot be more receptive to them.
If I knew the technical scenario better I might be able to think of something else. How about having a processing queue that processes X requests (MAX) at any given time ? Setting the max message count on that queue can help.
If a delay is not permissible then you may have no other option other than to increase the memory
i would suggest you look into your app to see where/how the memroy are used first.
once you have a ballpark how much memory is needed to process an incoming request, you could partition the application and put a load balancer in front to route the request to different partitions based on number of requests being processed. this is not the most efficient approach but it is better than OOO.