GAE使用的内存比我的Java应用程序多得多

huangapple go评论78阅读模式
英文:

GAE using much more memory than my Java application

问题

我在Google App Engine上运行着一个Java应用(Spring Boot),然而我注意到我的Java应用的内存消耗与GAE显示的仪表板之间存在奇怪的差异。

在我的本地机器上使用VisualVM,我可以看到即使在高峰时段,它的内存消耗也不会超过100MB。我添加了一个Servlet来返回所使用的内存量:

@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";
}

我在GAE中部署的应用现在返回:

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

与此同时,GAE仪表板显示它的内存消耗约为350MB
内存仪表板图片链接

为什么会发生这种情况?这迫使我使用F2实例;如果我降级到F1,应用会继续失败和重新启动。

我注意到一旦我将我的定时作业从每30分钟更改为每2分钟运行一次,他们开始按每天40小时对前端实例进行计费,而在此更改之前大约为16小时,我只有一个运行中的实例。这是如何可能的?
实例计数图片链接

谢谢。

英文:

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(&quot;/&quot;)
public String index() {
  Runtime rt = Runtime.getRuntime();
  long total = rt.totalMemory();
  long free = rt.freeMemory();
  long used = total - free;
  return &quot;Total: &quot; + total / 1024 / 1024 + &quot;MB&lt;br&gt;Used: &quot; + used / 1024 / 1024 + &quot;MB&lt;br&gt;Free: &quot; + free / 1024 / 1024 + &quot;MB&quot;;
}

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

答案1

得分: 1

以下是您要翻译的内容:

这些差异之所以出现是因为Cloud Console显示了JVM进程的实际大小(其中包括堆栈帧、永久代空间、直接缓冲区、机器代码等),而实例适用的内存限制是指JVM堆。运行时使用了一些堆内存,这些堆内存被计入应用程序使用的总堆使用量。

现在,理解这些方法的作用以及如何计算可用的内存来进行分配非常重要:

totalMemory()

JVM当前使用的所有内存。通常情况下,它比maxMemory要低,因为JVM会惰性分配内存,“惰性”意味着最初会分配一些内存并使用它,如果需要新的内存块,则会进行另一个分配,直到分配完所有可用内存(maxMemory())。


maxMemory()

可用的最大堆内存(实例大小受此值限制)。


freeMemory()

当前由JVM分配但未使用的内存部分。


可以分配的“真实总内存”为:

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

因此,可能比rt.freeMemory()的输出更多可用内存。

英文:

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().

huangapple
  • 本文由 发表于 2020年10月10日 14:50:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/64290810.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定