Nitin Chemate
Nitin Chemate

Reputation: 9

Java Memory usage returning negative numbers on IBMi machine

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 -

  1. QSH - Inbuild IBMi shell
  2. Using IBMi batch job

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

Answers (2)

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

rzwitserloot
rzwitserloot

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:

  • Your JVM starts up.
  • It is ticking along. Lots of code runs. Garbage is piling up everywhere. None of it is cleaned.
  • 5 hours pass. Garbage everywhere.
  • You set 'initial memory usage'. This is [A]
  • you run a bunch of your DB read ops. More garbage.
  • The garbage collector decides to wake up and clean up the mess.
  • The current memory usage is way less than at [A]
  • You run more read ops. This takes some memory, but still less than at [A]
  • You check memory usage. It is thus negative as it's less than at [A]

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:

  • Unless you 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?

That sounds like java's GC is the dumbest thing ever

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

Related Questions