Reputation: 9
We wanted to evaluate java performance on IBMi machine and I am very to the IBMi world. I am running java program to perform database CRUD operations on IBMi machine to know the performance. To evaluate the performance we are capturing memory usage by capturing before and after usage by using below java code -
I am running program by using below two ways -
How we calculate memory usage is -->
long initialMemoryUsage = getMemoryUsage();
After getting initial memory usage I am performing some DB read operations for 1,00,000 records
long memoryUsageAfter = getMemoryUsage() - initialMemoryUsage // (initial memory captured);
private static long getMemoryUsage() {
Runtime runtime = Runtime.getRuntime();
return runtime.totalMemory() - runtime.freeMemory();
}
However sometimes I am getting negative numbers for memory usage. Anyone aware about reason behind this? Please correct me if I am using wrong way to capture the memory usage
Thanks in advance.
Ideally I should get positive memory usage numbers on IBMi world. Here problem is I am very new to IBMi world and not sure how memory works here. If anyone aware about it please feel free to share.
Upvotes: 0
Views: 114
Reputation: 75376
You want better metrics. For all practical purposes you run the same JVM as under AIX and you can use the documentation for that (this has changed a lot since I worked with IBM i).
You should use the IBM equivalent to Java Flight Recorder to gather the real numbers over time. This will give you statistics and graphs too. VisualVM may work too (JMX only perhaps)
Upvotes: 2
Reputation: 103018
Java has a garbage collector. The entire concept is broken. What you want fundamentally isn't how it works, and therefore, cannot be done.
Java does not 'clean garbage' as garbage occurs.
Here is a trivial sequence of events:
The concept of 'initial memory usage' is broken. There is no guaranteed way to measure 'I want to know the current memory load MINUS any garbage'. Your best bet is to run System.gc()
before taking your 'initial memory load' measurement, but this has two major problems:
System.gc()
everytime you measure mem load, the memoryUsageAfter
will be completely broken, as your 'current load' measurement will include a whole bunch of garbage. And system.gc is generally extremely expensive.System.gc
is just a hint. It does not mean the garbage collector will actually run, nor that it will fully clean all garbage, nor that it means that all possible garbage will be found, nor that the garbage collector will run RIGHT NOW and that System.gc
won't return until it's all been found, discarded, and runtime.totalMemory()
's reports report accordingly.Hence, what you want fundamentally is never going to work. Take a step back. Why do you want to measure that, what are you trying to accomplish with measuring?
It's not. Letting garbage build up and then cleaning it all is a lot more efficient on a 'per kilo of garbage removed' sense than cleaning all garbage as you see it. On server environments, a system has a set amount of memory that it 'for that process' and there is zero point 'keeping it tidy' - you can make as much of a mess in that area as you want, do whatever it most efficient. Hence why java just lets the garbage pile up. It won't GC 'just cuz'. It'll wait for a good opportunity and tends to let it stack up.
I'm oversimplifying how it works by a very large margin - it's far, far more complex than this. This is bad news for your question: It means trying to determine how much memory is taken up by some code by way of checking the delta between 'total' and 'free' memory is utterly pointless.
Upvotes: 3