Eclipse极致性能调优

直接复制如下到eclipse.ini里面html

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-Xverify:none
-Xmn256m
-Xms1024m
-Xmx1024m
-Xss2m
-XX:PermSize=256m
-XX:MaxPermSize=256m
-XX:CompileThreshold=10000
-XX:MaxGCPauseMillis=10
-XX:MaxHeapFreeRatio=70
-XX:+UseFastAccessorMethods
-XX:+FailOverToOldVerifier
-XX:NewSize=280m
-XX:MaxNewSize=280m
-XX:CMSMarkStackSize=8M
-XX:CMSMarkStackSizeMax=32M
-XX:+DisableExplicitGC
-XX:+TraceClassLoading
-XX:+TraceClassUnloading
-XX:+CMSPermGenSweepingEnabled
-XX:CMSInitiatingOccupancyFraction=85
-XX:ReservedCodeCacheSize=64m
-verbose:gc
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:gc.log

最近项目愈来愈大,有个项目2G左右。是一个多平台多项目的组合。eclipse启动有些受不了了。并且有些类几千行,改一下卡一下。java

一直用的myeclipse6.5,由于不占内存,启动快。后来想,过几年总要被新产品替代。索性直接用eclipse得了。可是发现最新的eclipse也是慢得很。linux

虽然本身之前也有经验调整一些启动参数,但效果很差。因而乎百度求最优解决方案。算法

首先把你eclipse不要的启动项,验证什么的都干掉。具体的请百度之。sql

 

而后就是eclipse启动参数!启动速度刚刚的啊。。。看加粗的部分。。。apache

若是加入后不能启动,试着去掉最下面的几行参数看看,要一行行的试,不要都去掉了。或者将前面的参数值设置小一点。各个参数以前可能会互相影响的。缓存

-vm
D:/java/jdk6/bin
-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.200.v20120522-1813
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
-vmargs
-server
-Dosgi.requiredJavaVersion=1.5
-Xms1024m
-Xmx1024m
-Xss2m
-XX:PermSize=128m
-XX:MaxPermSize=128m
-XX:+UseParallelGC
-Xverify:none 
-XX:+DisableExplicitGC 
-Xnoclassgc 
#-XX:+UseParNewGC 
#-XX:+UseConcMarkSweepGC 
-XX:CMSInitiatingOccupancyFraction=85 
-XX:ReservedCodeCacheSize=150m
服务器

 

 

点击下面的查看:多线程

老外的方法并发

 

国内牛人写的方法

 

具体参数的说明

 

下面是后来看到的一篇文章,转贴在这里。http://www.cnblogs.com/chen77716/archive/2010/06/26/2130807.html

 

最近因项目存在内存泄漏,故进行大规模的JVM性能调优 , 现把经验作一记录。

1、JVM内存模型及垃圾收集算法

 1.根据Java虚拟机规范,JVM将内存划分为:

  • New(年轻代)
  • Tenured(年老代)
  • 永久代(Perm)

  其中New和Tenured属于堆内存,堆内存会从JVM启动参数(-Xmx:3G)指定的内存中分配,Perm不属于堆内存,有虚拟机直接分配,但能够经过-XX:PermSize -XX:MaxPermSize 等参数调整其大小。

  • 年轻代(New):年轻代用来存放JVM刚分配的Java对象
  • 年老代(Tenured):年轻代中通过垃圾回收没有回收掉的对象将被Copy到年老代
  • 永久代(Perm):永久代存放Class、Method元信息,其大小跟项目的规模、类、方法的量有关,通常设置为128M就足够,设置原则是预留30%的空间。

New又分为几个部分:

  • Eden:Eden用来存放JVM刚分配的对象
  • Survivor1
  • Survivro2:两个Survivor空间同样大,当Eden中的对象通过垃圾回收没有被回收掉时,会在两个Survivor之间来回Copy,当知足某个条件,好比Copy次数,就会被Copy到Tenured。显然,Survivor只是增长了对象在年轻代中的逗留时间,增长了被垃圾回收的可能性。

 2.垃圾回收算法

  垃圾回收算法能够分为三类,都基于标记-清除(复制)算法:

  • Serial算法(单线程)
  • 并行算法
  • 并发算法

  JVM会根据机器的硬件配置对每一个内存代选择适合的回收算法,好比,若是机器多于1个核,会对年轻代选择并行算法,关于选择细节请参考JVM调优文档。

  稍微解释下的是,并行算法是用多线程进行垃圾回收,回收期间会暂停程序的执行,而并发算法,也是多线程回收,但期间不中止应用执行。因此,并发算法适用于交互性高的一些程序。通过观察,并发算法会减小年轻代的大小,其实就是使用了一个大的年老代,这反过来跟并行算法相比吞吐量相对较低。

  还有一个问题是,垃圾回收动做什么时候执行?

  • 当年轻代内存满时,会引起一次普通GC,该GC仅回收年轻代。须要强调的时,年轻代尽是指Eden代满,Survivor满不会引起GC
  • 当年老代满时会引起Full GC,Full GC将会同时回收年轻代、年老代
  • 当永久代满时也会引起Full GC,会致使Class、Method元信息的卸载

  另外一个问题是,什么时候会抛出OutOfMemoryException,并非内存被耗空的时候才抛出

  • JVM98%的时间都花费在内存回收
  • 每次回收的内存小于2%

  知足这两个条件将触发OutOfMemoryException,这将会留给系统一个微小的间隙以作一些Down以前的操做,好比手动打印Heap Dump。

2、内存泄漏及解决方法

 1.系统崩溃前的一些现象:

  • 每次垃圾回收的时间愈来愈长,由以前的10ms延长到50ms左右,FullGC的时间也有以前的0.5s延长到四、5s
  • FullGC的次数愈来愈多,最频繁时隔不到1分钟就进行一次FullGC
  • 年老代的内存愈来愈大而且每次FullGC后年老代没有内存被释放

 以后系统会没法响应新的请求,逐渐到达OutOfMemoryError的临界值。

 2.生成堆的dump文件

 经过JMX的MBean生成当前的Heap信息,大小为一个3G(整个堆的大小)的hprof文件,若是没有启动JMX能够经过Java的jmap命令来生成该文件。

 3.分析dump文件

 下面要考虑的是如何打开这个3G的堆信息文件,显然通常的Window系统没有这么大的内存,必须借助高配置的Linux。固然咱们能够借助X-Window把Linux上的图形导入到Window。咱们考虑用下面几种工具打开该文件:

  1. Visual VM
  2. IBM HeapAnalyzer
  3. JDK 自带的Hprof工具

 使用这些工具时为了确保加载速度,建议设置最大内存为6G。使用后发现,这些工具都没法直观地观察到内存泄漏,Visual VM虽能观察到对象大小,但看不到调用堆栈;HeapAnalyzer虽然能看到调用堆栈,却没法正确打开一个3G的文件。所以,咱们又选用了Eclipse专门的静态内存分析工具:Mat。

 4.分析内存泄漏

 经过Mat咱们能清楚地看到,哪些对象被怀疑为内存泄漏,哪些对象占的空间最大及对象的调用关系。针对本案,在ThreadLocal中有不少的JbpmContext实例,通过调查是JBPM的Context没有关闭所致。

 另,经过Mat或JMX咱们还能够分析线程状态,能够观察到线程被阻塞在哪一个对象上,从而判断系统的瓶颈。

 5.回归问题

   Q:为何崩溃前垃圾回收的时间愈来愈长?

   A:根据内存模型和垃圾回收算法,垃圾回收分两部分:内存标记、清除(复制),标记部分只要内存大小固定时间是不变的,变的是复制部分,由于每次垃圾回收都有一些回收不掉的内存,因此增长了复制量,致使时间延长。因此,垃圾回收的时间也能够做为判断内存泄漏的依据

   Q:为何Full GC的次数愈来愈多?

   A:所以内存的积累,逐渐耗尽了年老代的内存,致使新对象分配没有更多的空间,从而致使频繁的垃圾回收

   Q:为何年老代占用的内存愈来愈大?

   A:由于年轻代的内存没法被回收,愈来愈多地被Copy到年老代

3、性能调优

 除了上述内存泄漏外,咱们还发现CPU长期不足3%,系统吞吐量不够,针对8core×16G、64bit的Linux服务器来讲,是严重的资源浪费。

 在CPU负载不足的同时,偶尔会有用户反映请求的时间过长,咱们意识到必须对程序及JVM进行调优。从如下几个方面进行:

  • 线程池:解决用户响应时间长的问题
  • 链接池
  • JVM启动参数:调整各代的内存比例和垃圾回收算法,提升吞吐量
  • 程序算法:改进程序逻辑算法提升性能

  1.Java线程池(java.util.concurrent.ThreadPoolExecutor)

    大多数JVM6上的应用采用的线程池都是JDK自带的线程池,之因此把成熟的Java线程池进行罗嗦说明,是由于该线程池的行为与咱们想象的有点出入。Java线程池有几个重要的配置参数:

  • corePoolSize:核心线程数(最新线程数)
  • maximumPoolSize:最大线程数,超过这个数量的任务会被拒绝,用户能够经过RejectedExecutionHandler接口自定义处理方式
  • keepAliveTime:线程保持活动的时间
  • workQueue:工做队列,存放执行的任务

    Java线程池须要传入一个Queue参数(workQueue)用来存放执行的任务,而对Queue的不一样选择,线程池有彻底不一样的行为:

  • SynchronousQueue: 一个无容量的等待队列,一个线程的insert操做必须等待另外一线程的remove操做,采用这个Queue线程池将会为每一个任务分配一个新线程
  • LinkedBlockingQueue : 无界队列,采用该Queue,线程池将忽略 maximumPoolSize参数,仅用corePoolSize的线程处理全部的任务,未处理的任务便在LinkedBlockingQueue中排队
  • ArrayBlockingQueue: 有界队列,在有界队列和 maximumPoolSize的做用下,程序将很难被调优:更大的Queue和小的maximumPoolSize将致使CPU的低负载;小的Queue和大的池,Queue就没起动应有的做用。

    其实咱们的要求很简单,但愿线程池能跟链接池同样,能设置最小线程数、最大线程数,当最小数<任务<最大数时,应该分配新的线程处理;当任务>最大数时,应该等待有空闲线程再处理该任务。

    但线程池的设计思路是,任务应该放到Queue中,当Queue放不下时再考虑用新线程处理,若是Queue满且没法派生新线程,就拒绝该任务。设计致使“先放等执行”、“放不下再执行”、“拒毫不等待”。因此,根据不一样的Queue参数,要提升吞吐量不能一味地增大maximumPoolSize。

    固然,要达到咱们的目标,必须对线程池进行必定的封装,幸运的是ThreadPoolExecutor中留了足够的自定义接口以帮助咱们达到目标。咱们封装的方式是:

  • 以SynchronousQueue做为参数,使maximumPoolSize发挥做用,以防止线程被无限制的分配,同时能够经过提升maximumPoolSize来提升系统吞吐量
  • 自定义一个RejectedExecutionHandler,当线程数超过maximumPoolSize时进行处理,处理方式为隔一段时间检查线程池是否能够执行新Task,若是能够把拒绝的Task从新放入到线程池,检查的时间依赖keepAliveTime的大小。

  2.链接池(org.apache.commons.dbcp.BasicDataSource)

    在使用org.apache.commons.dbcp.BasicDataSource的时候,由于以前采用了默认配置,因此当访问量大时,经过JMX观察到不少Tomcat线程都阻塞在BasicDataSource使用的Apache ObjectPool的锁上,直接缘由当时是由于BasicDataSource链接池的最大链接数设置的过小,默认的BasicDataSource配置,仅使用8个最大链接。

    我还观察到一个问题,当较长的时间不访问系统,好比2天,DB上的MySQL会断掉因此的链接,致使链接池中缓存的链接不能用。为了解决这些问题,咱们充分研究了BasicDataSource,发现了一些优化的点:

  • Mysql默认支持100个连接,因此每一个链接池的配置要根据集群中的机器数进行,若有2台服务器,可每一个设置为60
  • initialSize:参数是一直打开的链接数
  • minEvictableIdleTimeMillis:该参数设置每一个链接的空闲时间,超过这个时间链接将被关闭
  • timeBetweenEvictionRunsMillis:后台线程的运行周期,用来检测过时链接
  • maxActive:最大能分配的链接数
  • maxIdle:最大空闲数,当链接使用完毕后发现链接数大于maxIdle,链接将被直接关闭。只有initialSize < x < maxIdle的链接将被按期检测是否超期。这个参数主要用来在峰值访问时提升吞吐量。
  • initialSize是如何保持的?通过研究代码发现,BasicDataSource会关闭全部超期的链接,而后再打开initialSize数量的链接,这个特性与minEvictableIdleTimeMillis、timeBetweenEvictionRunsMillis一块儿保证了全部超期的initialSize链接都会被从新链接,从而避免了Mysql长时间无动做会断掉链接的问题。

  3.JVM参数

    在JVM启动参数中,能够设置跟内存、垃圾回收相关的一些参数设置,默认状况不作任何设置JVM会工做的很好,但对一些配置很好的Server和具体的应用必须仔细调优才能得到最佳性能。经过设置咱们但愿达到一些目标:

  • GC的时间足够的小
  • GC的次数足够的少
  • 发生Full GC的周期足够的长

  前两个目前是相悖的,要想GC时间小必需要一个更小的堆,要保证GC次数足够少,必须保证一个更大的堆,咱们只能取其平衡。

   (1)针对JVM堆的设置通常,能够经过-Xms -Xmx限定其最小、最大值,为了防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,咱们一般把最大、最小设置为相同的值
   (2)年轻代和年老代将根据默认的比例(1:2)分配堆内存,能够经过调整两者之间的比率NewRadio来调整两者之间的大小,也能够针对回收代,好比年轻代,经过 -XX:newSize -XX:MaxNewSize来设置其绝对大小。一样,为了防止年轻代的堆收缩,咱们一般会把-XX:newSize -XX:MaxNewSize设置为一样大小

   (3)年轻代和年老代设置多大才算合理?这个我问题毫无疑问是没有答案的,不然也就不会有调优。咱们观察一下两者大小变化有哪些影响

  • 更大的年轻代必然致使更小的年老代,大的年轻代会延长普通GC的周期,但会增长每次GC的时间;小的年老代会致使更频繁的Full GC
  • 更小的年轻代必然致使更大年老代,小的年轻代会致使普通GC很频繁,但每次的GC时间会更短;大的年老代会减小Full GC的频率
  • 如何选择应该依赖应用程序对象生命周期的分布状况:若是应用存在大量的临时对象,应该选择更大的年轻代;若是存在相对较多的持久对象,年老代应该适当增大。但不少应用都没有这样明显的特性,在抉择时应该根据如下两点:(A)本着Full GC尽可能少的原则,让年老代尽可能缓存经常使用对象,JVM的默认比例1:2也是这个道理 (B)经过观察应用一段时间,看其余在峰值时年老代会占多少内存,在不影响Full GC的前提下,根据实际状况加大年轻代,好比能够把比例控制在1:1。但应该给年老代至少预留1/3的增加空间

  (4)在配置较好的机器上(好比多核、大内存),能够为年老代选择并行收集算法: -XX:+UseParallelOldGC ,默认为Serial收集

  (5)线程堆栈的设置:每一个线程默认会开启1M的堆栈,用于存放栈帧、调用参数、局部变量等,对大多数应用而言这个默认值太了,通常256K就足用。理论上,在内存不变的状况下,减小每一个线程的堆栈,能够产生更多的线程,但这实际上还受限于操做系统。

  (4)能够经过下面的参数打Heap Dump信息

  • -XX:HeapDumpPath
  • -XX:+PrintGCDetails
  • -XX:+PrintGCTimeStamps
  • -Xloggc:/usr/aaa/dump/heap_trace.txt

    经过下面参数能够控制OutOfMemoryError时打印堆的信息

  • -XX:+HeapDumpOnOutOfMemoryError

 请看一下一个时间的Java参数配置:(服务器:Linux 64Bit,8Core×16G)

 JAVA_OPTS="$JAVA_OPTS -server -Xms3G -Xmx3G -Xss256k -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/aaa/dump -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/usr/aaa/dump/heap_trace.txt -XX:NewSize=1G -XX:MaxNewSize=1G"

通过观察该配置很是稳定,每次普通GC的时间在10ms左右,Full GC基本不发生,或隔很长很长的时间才发生一次

经过分析dump文件能够发现,每一个1小时都会发生一次Full GC,通过多方求证,只要在JVM中开启了JMX服务,JMX将会1小时执行一次Full GC以清除引用,关于这点请参考附件文档。

 4.程序算法调优:本次不做为重点

参考资料:

http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

相关文章
相关标签/搜索