Tomcat 运行时的JVM调优

前言

TOMCAT的性能直接取决于JVM,所以对于TOMCAT的性能调优也大都集中在配置TOMCAT运行时的JVM参数上

JVM内存机制

JVM为java虚拟机,使用来编译执行java代码用。java内存分为register,stack,heap,static storage,constant storage,permanent generation space.

Register

寄存器(register)。这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部。但是寄存器的数量极其有限,所以寄存器由编译器根据需求进行分配。你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象。

stack

位于通用 RAM(random-access memory,随机访问存储器)中,但通
过它的“堆栈指针”可以从处理器那里获得直接支持。堆栈指针若向下移动,则分配
新的内存;若向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次
于寄存器。创建程序时,Java 编译器必须知道存储在堆栈内所有数据的确切大小和生
命周期,因为它必须生成相应的代码,以便上下移动堆栈指针。这一约束限制了程序
的灵活性,所以虽然某些 Java 数据存储于堆栈中——特别是对象引用,但是 Java 对
象并不存储于其中

heap

堆(heap)。一种通用性的内存池(也存在于 RAM 区) ,用于存放所有的 Java 对象。
堆不同于堆栈的好处是:编译器不需要知道要从堆里分配多少存储区域,也不必知道
存储的数据在堆里存活多长时间。因此,在堆里分配存储有很大的灵活性。当你需要
创建一个对象时,只需用 new 写一行简单的代码,当执行这行代码时,会自动在堆里
进行存储分配。当然,为这种灵活性必须要付出相应的代价。用堆进行存储分配比用
堆栈进行存储存储需要更多的时间 (如果确实可以在 Java 中像在 C++中一样用栈保存
对象) 。

static storage

静态存储(static storage)
。这里的“静态”是指“在固定的位置” (尽管也在 RAM 里)。
静态存储里存放程序运行时一直存在的数据。你可用关键字 Static 来标识一个对象的
特定元素是静态的,但 Java 对象本身从来不会存放在静态存储空间里。

constant storage

常量存储(constant storage)。常量值通常直接存放在程序代码内部,这样做是安全的,
因为它们永远不会被改变。有时,在嵌入式系统中,常量本身会和其它部分隔离开,
所以在这种情况下,可以选择将其存放在 ROM(read-only memory,只读存储器)中。

Permanent Generation Space

简单而言,便是加载类的区域,详细介绍参见这里

总结

寄存器存放指令、栈存放对象引用、堆存放对象、PerGen Space加载和存放类

TOMCAT调优

JVM会对heap和PerGen Space执行垃圾回收,回收和分配空间本身都会消耗一定性能。所以TOMCAT调优的核心就在于选择哪一种模式的回收器,以及如何减少垃圾回收器执行的次数。

具体点也就说:将堆内存的初始化大小和极限大小指定相同的值,将类加载区的PerGen Space的初始大小和极限大小指定相同的值,这样避免垃圾JVM频繁的分配资源和垃圾回收。以及根据具体的系统配置选择垃圾回收器的类型,比如并行、并发回收等。详细内容如下

At this point we've covered the basics and are ready to begin examining the JVM options that are available to us. Please note that while these options can be used for any application running on the JVM, this article will focus sole only how they can be applied to Tomcat. The usage of these options for other applications may or may not be appropriate.

Note: For simplicity, it is assumed that you are running an Oracle Hotspot JVM.

General Options

-Xms and -Xmx

These settings are used to define the size of the heap used by the JVM. -Xms defines the initial size of the heap and -Xmx defines the maximum size of the heap. Specific values for these options will depend on the number of applications and the requirements of each application deployed to a Tomcat instance.

With regard to Tomcat, it is recommended that the initial and maximum values for heap size be set to the same value. This is often referred to as a fully committed heap and this will instruct the JVM to create a heap that is initially at its maximum size and prevent several full garbage collections from occurring as the heap expands to its maximum size.

-XX:PermSize and -XX:MaxPermSize

These settings are used to define the size of the permanent generation space. -XX:PermSizedefines the initial value and -XX:MaxPermSize defines the maximum value.

With regard to Tomcat, it is recommended that the initial and maximum values for the size of the permanent generation be set to the same value. This will instruct the JVM to create the permanent generation so that it is initially at its maximum size and prevent possible full garbage collections from occurring as the permanent generation expands to its maximum size.

At this point, you might be thinking that this seems awful similar to the -Xms and -Xmx options, and while the concept is the same, “PermGen” or permanent generation, refers to the location in memory where the JVM stores the class files that have been loaded into memory. This is different and distinct from the heap (specified by -Xms and -Xmx) which is where the JVM stores the object instances used by an application.

One final note, if the PermGen space becomes full (regardless of the availability of memory in the heap) then the JVM will attempt a full garbage collection to reclaim space. This can often be a source of problems for applications which dynamically create or load a large number of classes. Proper sizing of -XX:PermSize and -XX:MaxPermSize for your applications will allow you to work around this issue.

-Xss

This setting determines the size of the stack for each thread in the JVM. The specific value that you should use will vary depending on the requirements of the applications deployed to Tomcat, however in most cases the default value used by the JVM is too large.

For a typical installation, this value can be lowered, saving memory and increasing the number of threads that can be run on a system. The easiest way to determine a value for your system is to start out with a very low value, for example 128k. Then run Tomcat and look for a StackOverFlow exception in the logs. If you see the exception, then gradually increase the value and restart Tomcat. When the exceptions disappear, you have found the minimal value which works for your deployment.

-server

This setting will select the Java HotSpot Server VM. This will instruct the VM that it is running in a server environment and the default configurations will be changed accordingly.

Note, this option is really only needed when running 32-bit Windows, as 32-bit Solaris and 32-bit Linux installations with two or more CPU's and 2GB or more of RAM will enable this option by default. In addition, all 64-bit OS's have this option enabled by default as there is no 64-bit client VM.

For a comprehensive list of JVM options, please see the article Java HotSpot VM Options.

Selecting a Collector

For many users, tuning the basic options I mentioned in the previous section will be sufficient for their applications. However, for larger applications or applications which just require larger heap sizes these options may not be sufficient. If your Tomcat installation fits this profile then you'll want to take one further step and tune the collector.

To begin tuning the collector, you need to pick the right collector for your application. The JVM ships with three commonly used collectors: the serial collector, the parallel collector and the concurrent collector. In most cases when running Tomcat, you'll be using either the parallel collector or the concurrent collector. The difference between the two being that the parallel collector typically offers the better throughput, while the concurrent collector often offers lower pause times.

The parallel collector can be enabled by adding -XX:+UseParallelGC to CATALINA_OPTS or the concurrent collector can be enabled by adding -XX:+UseConcMarkSweepGC to CATALINA_OPTS (you would never want to have both options enabled). As to which of the collectors you should be using, it is difficult to give a blanket recommendation. I would suggest that you give both a try, measure the results and use that to make your decision.

Once you have selected a collector, it is possible to take one further step and apply some configuration settings which are specific to the collector. That being said, most of the time the JVM will detect and set excellent values for these options. You should not attempt to manually configure these unless you have a good understanding of how the specific garbage collector is working, you are applying rule number one from above and you really know what you are doing. That said, I'm going to talk about two options, one for the parallel collector and one for the concurrent collector.

When you specify the option to run the parallel collector, it will only run on the young generation. This means that multiple threads will be used to process the young generation, but the old generation will continue to be processed by a single thread. To enable parallel compaction of the old generation space you can enable the option -XX:+UseParallelOldGC. Note that this option will help the most when enabled on a system with many processors.

When you specify the option to run the concurrent collector, it is important to realize that garbage collection will happen concurrently with the application. This means that garbage collection will consume some of the processor resources that would have otherwise been available to the application. On systems with a large number of processors, this is typically not a problem. However, if your system has only one or two processors then you will likely want to enable the -XX:+CMSIncrementalMode option. This option enables incremental mode for the collector, which instructs the collector to periodically yield the processor back to the application and essentially prevents the collector from running for too long.

Conclusion

Congratulations! If you're reading this then you made it all the way through the article. If you're still a little confused at this point, that is OK and I would say normal. Tuning the JVM and the inner workings of the garbage collectors is not an easy subject.

If you'd like to get some additional information on the subject, I would strongly suggest continuing on with this article from Oracle, Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning. It is very technical and should be able to fill in any of the gaps left from this article.

参考资料地址:

http://www.tomcatexpert.com/blog/2011/11/22/performance-tuning-jvm-running-tomcat

https://blogs.oracle.com/jonthecollector/entry/presenting_the_permanent_generation

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容