简体   繁体   English

了解JVM内存优化

[英]Understanding JVM Memory Optimization

I have recently taken up task to benchmark and optimize memory utilization in our Java Servers, while fixing the memory leaks if any. 我最近承担了在Java服务器中基准测试和优化内存利用率的任务,同时修复了内存泄漏(如果有)。 We have 4 JVM servers running in a single machine which has 15G Physical memory and 32G Swap memory. 我们有4台JVM服务器在一台机器上运行,该机器具有15G物理内存和32G交换内存。 Following is free -m snapshot. 以下是free -m快照。

              total        used        free         shared  buff/cache    available
Mem:          15289       14786         392           1         110         342
Swap:         32767        3776       28991

If I understand correctly:- 如果我正确理解:-

  1. Most of the physical memory is in use and most of the swap memory is free. 大部分物理内存正在使用,而大多数交换内存是空闲的。
  2. A low of amount of memory is actually buffered. 实际上会缓冲少量的内存。
  3. I have 48GB of virtual memory 我有48GB的虚拟内存

Now each of my server is running with 7G Maximum heap size set with -Xmx option. 现在,我的每个服务器都在使用-Xmx选项设置的7G最大堆大小下运行。 Following is the output from GC Utils 以下是GC Utils的输出

$ jstat -gcutil 8317
  S0     S1     E      O      M     CCS      YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00   6.97   0.22  96.77  91.89     72    8.027    33   10.975   19.002
$ jstat -gcutil 8332
  S0     S1     E      O      M     CCS      YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00   5.17  50.76  96.57  91.65    274   51.001    51  179.106  230.107
$ jstat -gcutil 8249
  S0     S1     E      O      M     CCS      YGC     YGCT    FGC    FGCT     GCT
  0.00   2.10  80.37  69.53  96.87  92.08    421   69.478    13   56.569  126.047
$ jstat -gcutil 23875
  S0     S1     E      O      M     CCS      YGC     YGCT    FGC    FGCT     GCT
 27.91   0.00  37.07  86.29  97.59  94.60    232    7.294     2    0.030    7.324

After running manual Full GC, it completely freed young and old generation for all the servers. 在运行手动Full GC之后,它完全释放了所有服务器的年轻一代和老一代。 Now I need help in understanding this characterstic, basically am I correct in assuming following? 现在,我需要帮助来理解这个特性,基本上我是否正确假设以下内容?

  1. Objects move depending on longevity and surviving count as Eden -> S0 -> S1 -> O. 对象的寿命和寿命取决于Eden-> S0-> S1->O。
  2. Three of the servers have Old Gen > Young Gen. Does that mean that the Full GC is not running enough? 其中三台服务器具有“旧一代”>“年轻一代”。这是否意味着Full GC运行不足?
  3. Or, I need to tweak SurvivorRatio and NewRatio etc. settings to give Young Generation more chance to collect objects, and delay moving the objects to old space. 或者,我需要调整SurvivorRatio和NewRatio等设置,以使Young Generation有更多机会收集对象,并延迟将对象移动到旧空间。
  4. However increasing Y space means slower short GC and poor application throughput, Should I increase memory and stop worrying about tweaking? 但是,增加Y空间意味着更短的GC速度和较差的应用程序吞吐量,我应该增加内存并停止担心调整吗?

I am asking this, because Full GC does free all memory, so there is no memory leak but How can I strike a balance between memory usage and application troughput by adjusting GC settings. 我问这个问题,因为Full GC会释放所有内存,所以没有内存泄漏,但是如何通过调整GC设置在内存使用和应用程序吞吐量之间取得平衡。 Could anyone provide more direction or reccomendation by taking above machine state into consideration? 任何人都可以通过考虑以上机器状态来提供更多指导或建议吗?

JVM Details:
Java Version: openjdk version "1.8.0_131" Server Class
GC: Parallel Collector(Default one)

In short: Basically going for memory usages at a certain point in time is a bad idea, if you want to understand your system. 简而言之:如果您想了解系统,那么基本上在某个时间点使用内存将是一个坏主意。 It is a lot more helpful to look at the behaviour over time. 查看一段时间内的行为会更有帮助。 To do so, use wither the JConsole or professional profilers like YourKit or JProfiler. 为此,请使用JConsole或专业分析器,如YourKit或JProfiler。 On the other hand, the defaults of the Hotspot-VM are quite reasonable, so unless you have a very specific application-memory-profile, you will probably not win a lot by fiddling and win more by simply throwing more hardware at the problem. 另一方面,Hotspot-VM的默认设置是相当合理的,因此,除非您有一个非常特定的应用程序内存配置文件,否则您可能不会因摆弄而获得很多收益,而仅仅通过在问题上投入更多的硬件就不会获得更多收益。

Be aware, that your server is most probably under-dimensioned (see question 4) 请注意,您的服务器可能尺寸不足(请参阅问题4)

Long answer: 长答案:

Question 1: How do objects proceed through the different memory-areas? 问题1: 对象如何穿过不同的存储区域? Each object is created in eden space. 每个对象都在eden空间中创建。 The first minor garbage-collection (which is also triggered a major collections) will put that object either in survivor (if there is sufficient space) or directly into tenured. 第一个次要垃圾回收(也会触发主要垃圾回收)会将对象放到幸存者中(如果有足够的空间)或直接置于使用权中。 For objects already in survivor, they are moved from one survivor space to the other and at some point (determined by a heuristic within the VM) are moved into tenured. 对于已经存在于幸存者中的对象,它们从一个幸存者空间移动到另一个幸存者空间,并在某个时刻(由VM中的启发式方法确定)被转移到保管期。 The rule always holds, that at least one survivor is always empty. 该规则始终成立,至少有一个幸存者永远是空的。

Question 2: Does a greater occupation of old than young mean, you are not collecting often enough? 问题2: 您对旧事物的收集不够吗? Definitely not. 当然不。 Garbage collection in Java works the better (more efficient), if it is executed seldom. 如果很少执行垃圾收集,则Java中的垃圾收集效果更好(效率更高)。 Basically, if more objects died since the last collection, the collection is more efficient as it can clean up more memory at once. 基本上,如果自上一个集合以来有更多的对象死亡,则该集合效率更高,因为它可以一次清理更多的内存。 The gc is designed to let tenured to fill up until it reaches a very high fill level (close to 100%) prior to triggering a full-gc. gc设计为在触发全gc之前让任期填补直至达到很高的填充水平(接近100%)。 We observe production systems not doing a full-gc for weeks because the young generations are large enough so that all temporary allocations die within eden or survivor. 我们观察到生产系统在数周内没有执行全功能,因为年轻一代足够大,因此所有临时分配都在伊甸园或幸存者中死亡。 Apart from that: All your caches, Spring Beans or whatever will always be placed in tenured. 除此之外:您所有的缓存,Spring Bean或其他任何内容都将始终存放在使用权中。

Question 3: Should I tweak memory parameters to optimize memory-consumption? 问题3: 是否应该调整内存参数以优化内存消耗? By all means: NO! 绝对:不! Never touch that stuff unless you know exactly, what you are doing. 除非您确切知道自己在做什么,否则切勿触摸这些东西。 Enlarging the young generations might cause your application to die of out-of-memory-errors. 扩大年轻一代可能会导致您的应用程序因内存不足错误而死亡。 You should be very clear about the long-term-behaviour of your application before fiddling with that stuff and the heuristics of the hotspot-VM are quite good. 在摆弄这些东西之前,您应该非常清楚应用程序的长期性能,并且热点VM的启发式方法还不错。 On the other hand, it is possible to significantly reduce gc-times if you know, what you are doing. 另一方面,如果您知道自己在做什么,则可以大大减少gc时间。 In one system (the one, mentioned above) we saw a decrease of minor collections from once ~20 seconds to once in several minutes and an almost complete stop in full-gcs after tweaking. 在一个系统(上面提到的系统)中,我们看到次要收集从约20秒减少到几分钟内一次,并且在调整后几乎完全停止了全gcs。 But in the process of learning and understanding, how our application behaved memory-wise over time, we also killed a lot executions. 但是在学习和理解的过程中,随着时间的流逝,我们的应用程序在内存方面的行为如何,我们也杀死了很多执行程序。

Question 4: Should I increase memory instead of fiddling? 问题4: 我应该增加记忆力而不是摆弄吗? Depends. 要看。 Your system is not healthy as it is. 您的系统本身并不健康。 Increasing memory will make that worse. 增加内存会使情况变得更糟。 You are running 4 VMs with a heap of up to 7g (total 28g) on a system with 16g physical memory. 您正在具有16g物理内存的系统上运行4个VM,其最大堆内存为7g(总共28g)。 If all your VMs expand memory consumption to the maximum, you will see a lot of swapping and that will definitely reduce performance to a level you can hardly imagine. 如果所有虚拟机都将内存消耗最大化,那么您将看到很多交换,这肯定会将性能降低到难以想象的水平。 I would go for more hardware in the scenario as it is, especially considering, that the real consumption of a java application is roughly 1.5 times the heap (you have to add permgen/metaspace, the stack, codecache and the memory the vm itself consumes). 我会在这种情况下寻求更多的硬件,特别是考虑到Java应用程序的实际消耗大约是堆的1.5倍(您必须添加permgen / metaspace,堆栈,代码缓存和vm本身消耗的内存)。 If you know for sure, your application is running with -xmx7g you could start there: Increasing the overall memory while reducing the old-gen part so that the absolute old-size stays unchanged. 如果可以肯定地知道,您的应用程序是使用-xmx7g运行的,则可以从那里开始:在减少旧生成部分的同时增加总内存,以使旧的绝对大小保持不变。 That however means a lot of more hardware. 但是,这意味着需要更多的硬件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM