Reddy Stark
Reddy Stark

Reputation: 31

GAE using much more memory than my Java application

I have a Java app (Spring Boot) running on Google App Engine; however, I see weird differences between my Java app memory consumption and the dashboard shown by GAE.

In my local machine using a VisualVM I can see it doesn't consume over 100MB even at peak times, and I added a servlet to return the amount of memory used:

@GetMapping("/")
public String index() {
  Runtime rt = Runtime.getRuntime();
  long total = rt.totalMemory();
  long free = rt.freeMemory();
  long used = total - free;
  return "Total: " + total / 1024 / 1024 + "MB<br>Used: " + used / 1024 / 1024 + "MB<br>Free: " + free / 1024 / 1024 + "MB";
}

my deployed app in GAE right now returns:

Total: 91MB
Used: 69MB
Free: 21MB

at this same time, the GAE dashboard shows it's consuming around 350MB memory dashboard IMG url

Why did that happen? It forces me to use an F2 instance; if I downgrade to an F1, it keeps failing and restarting.

I noticed that once I changed my cronjob from every 30 min to run every 2 min, they started charging me for 40 hours per day in Frontend instances, it was around 16 hours before this change, and I have only 1 instance running. How is that possible? instance count img url

Thank you

Upvotes: 2

Views: 504

Answers (1)

tzovourn
tzovourn

Reputation: 1321

The reason you see these differences is due to the Cloud Console displaying the actual size of the JVM process(which includes stack frames, perm gen space, direct buffers, machine code, etc.) where the memory limit that applies for instances refers to the JVM heap. The runtime uses some heap memory which counted against the total heap usage by the app.

Now, it is important to understand what do these methods do and how to calculate the available memory to allocate:

totalMemory():

All memory currently used by JVM. It's usually lower than maxMemory because JVM allocates memory lazily, "lazily" meaning that some memory is allocated initially and used, and, if a new chunk of memory is needed, another allocation is done, up to all available memory (maxMemory()).


maxMemory():

Maximum available heap memory (instance size is limited to this value).


freeMemory():

Portion of memory currently both allocated by JVM and not used.


The "real total memory" that can be allocated is:

rt.freeMemory() + (rt.maxMemory() - rt.totalMemory())

So there can be more memory available than the output of rt.freeMemory().

Upvotes: 1

Related Questions