本文目录一览:
提高Java性能的几个高效用法
1、调整垃圾收集(GC)
由于垃圾收集的复杂性,很难发现你的应用的准确性能。不过,如果你真的想优化你的应用,你应该相应地处理垃圾收集。通用的准则是调整GC设置并同时执行性能分析。
一旦你对结果感到满意,你可以停止该过程并寻求其他优化方式。确保除了在平均事务处理时间之外,你还留心了异常值。这些异常值是造成Java应用缓慢的真正的罪魁祸首并且很难找到。
此外,你要明白应用运行期间性能下降的效应。在每单个cpu时钟内的缓慢操作是可以忽略的,但在每单个数据库事务中的缓慢操作则是非常昂贵的消耗。但是你应该根据性能短板选择你的优化策略,并应该根据工作负载来优化应用。
2、正确地选择适合你的GC算法
让我们更深入地探讨GC优化。毕竟,GC优化是要处理的整个优化问题中最基本的。目前,Java中有四种供你选择的垃圾收集算法。每种算法满足不同的需求,因此你要选择(适合你的需求的)。很多开发人员正是因为不了解GC算法而未能优化他们的应用。
这四个算法分别是串行回收器,并行/吞吐量回收器,CMS回收器和G1回收器。想要了解更多关于每种垃圾收集器的信息及它们是如何工作的,请查看这篇来自Takipi博客的非常棒的文章Garbage Collectors—Serial vs。 Parallel vs。 CMS vs。 G1。这篇文章同时还讨论了Java8对GC算法的影响及其他细节上的改变。让我们再回到GC算法上,根据Understanding Java Garbage Collection这篇文章所述,并发标记和清除GC(即”CMS”)算法才是适合网络服务端应用的最佳算法。并行GC算法适合那些内部可预测的应用。
G1和CMS是并发操作的理想选择,但仍然会引起(应用)频繁停顿。实际的选择取决于你如何取舍。举例来说,尽管选择并行算法会带来更长的GC停顿时间,但相较于其他GC算法,选择并行算法仍是一个好主意。
3、Java堆
Java内存堆在迎合内存需求方面担任了至关重要角色。通常更好的做法是初始时分配最小的堆,然后通过持续的测试不断增加它的大小。大多数时候优化问题都可以通过增加堆的大小解决,但如果存在大量的GC开销,则该解决方案不起作用。
GC开销还会使吞吐量急剧下降,进而使得应用难以形容的慢。此外,及早调整GC可以帮助你避免堆大小分配的问题。开始的时候,你可以选择任何1GB到8GB的堆大小。当你选择正确的堆大小,老生代和新生代对象的概念也就不需要了。总而言之,堆大小应该取决于老生代和新生代对象的比率,之前的GC优化和对象集合(即所有对象占用的内存大小)。
4、关键应用优化
关键代码优化是优化你的Java应用最好的方式。如果你的应用对GC和堆优化没有反应,那么最好是做架构改进并关注于你的应用是如何处理信息的。使用聪明的算法并管理好对象就能解决大量的问题,包括内存碎片,堆大小问题和垃圾收集的问题。
5、使用最优的函数
Java提供了多个函数来提升算法效率。如果你使用StringBuilder代替简单的String,你可以得到微乎其微的性能提升。不过,我们还有其他方式在代码层面进行优化。让我们看看下面这些优化方法。
使用StringBuilder代替+操作符。
避免使用iterator。
多使用栈带来的好处。
避免使用正则表达式,使用Apache Commons Lang作为代替。
远离递归。递归会占用大量资源!
看完阿里程序员做JVM调优,让我明白12K和40K的差距在哪
怎样才能做好性能调优?
关于性能调优,我先来说说的我的感受。Java性能调优不像是学一门编程语言,无法通过直线式的思维来掌握和应用,它对于工程师的技术广度和深度都有着较高的要求。
互联网时代,一个简单的系统就囊括了应用程序、数据库、容器、操作系统、网络等技术,线上一旦出现性能问题,就可能要你协调多方面组件去进行优化,这就是技术广度;而很多性能问题呢,又隐藏得很深,可能因为一个小小的代码,也可能因为线程池的类型选择错误..可归根结底考验的还是我们对这项技术的了解程度,这就是技术深度。
显然,性能调优不是一件容易的事。但有没有什么方法能把这件事情做好呢?
在这篇文章里,将从实战出发,精选高频性能问题,透过 Java 底层源码,提炼出优化思 路和它背后的实现原理,最后形成一套“学完就能用的调优方法论”。这也是很多一线大厂 对于高级工程师的要求,希望通过这个文章帮助你快速进阶。
Java调优
性能调优策略图
设计调优
JVM调优
多线程调优
数据库调优
Java程序优化
并行程序开发及优化
Java性能调优工具
实战演练场
最后
这篇文章适合所有Java程序员、软件设计师、架构师以及软件开发爱好者,对于在一定经验的java工程师,更能帮助突破技术瓶颈,深入Java内核开发!
希望本文能够在工作中对读者有所帮助。
jvm性能调优都做了什么
JVM是最好的软件工程之一,它为Java提供了坚实的基础,许多流行语言如Kotlin、Scala、Clojure、Groovy都使用JVM作为运行基础。一个专业的Java工程师必须要了解并掌握JVM,接下来就给大家分享Java基础知识中JVM调优相关知识点。
杭州Java基础知识学习之JVM调优讲解
JVM常见的调优参数包括:
-Xmx:指定java程序的最大堆内存, 使用java -Xmx5000M -version判断当前系统能分配的最大堆内存;
-Xms:指定最小堆内存, 通常设置成跟最大堆内存一样,减少GC;
-Xmn:设置年轻代大小。整个堆大小=年轻代大小+年老代大小。所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8;
-Xss:指定线程的最大栈空间, 此参数决定了java函数调用的深度, 值越大调用深度越深, 若值太小则容易出栈溢出错误(StackOverflowError);
-XX:PermSize:指定方法区(永久区)的初始值,默认是物理内存的1/64,在Java8永久区移除, 代之的是元数据区,由-XX:MetaspaceSize指定;
-XX:MaxPermSize:指定方法区的最大值, 默认是物理内存的1/4,在java8中由-XX:MaxMetaspaceSize指定元数据区的大小;
-XX:NewRatio=n:年老代与年轻代的比值,-XX:NewRatio=2, 表示年老代与年轻代的比值为2:1;
-XX:SurvivorRatio=n:Eden区与Survivor区的大小比值,-XX:SurvivorRatio=8表示Eden区与Survivor区的大小比值是8:1:1,因为Survivor区有两个(from, to)。
JVM实质上分为三大块,年轻代(YoungGen),年老代(Old Memory),及持久代(Perm,在Java8中被取消)。
年轻代大小选择
响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
年老代大小选择
响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例。
减少年轻代和年老代花费的时间,一般会提高应用的效率。
吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
较小堆引起的碎片问题
因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩。
java怎么高效调优接口
本来用DWR调用方法就是多线程的,线程总数与J2EE容器配置的有关。建议如下:如果你这个A()调用的接口一次只允许一个访问,那么需要在A所在的类里设置一个静态成员变量,如staticStringobject="some"。然后在A()方法一开始用synchronized(object)把代码都包含进来。这样可以确保一次只有一个访问。如果接口一次最多运行固定数目的访问,如10个。那么复杂一些,不过我估计你不是这个情况。一般建议这个固定数目与J2EE容器配置的线程数一致即可。上述方法都是为了防止接口被同时访问,但这样的后果就是前端用户会等待,甚至线程满。前端等待是没法的,后面慢,前面只有排队了。线程满的话,最好的方式是采用非阻塞的IO(NIO),不过那个很难做到。你提出的10秒终止方法是一种方案,不过关键在于如何终止一个方法的运行。很遗憾,Java不能任意终止一个方法的运行,不过对于接口操作,可以如下处理:a)如果接口是TCP/IP,那么可以通过强行关闭socket来终止。如:timer.schedule(newTimerTask(){publicvoidrun(){socket.close();}},10000);b)如果接口是用类库的话,看看它有没有设置timeout的地方,如果有,那么设置一下,如果没有,那么没法了。补充:你用了axis的setTimeout,理论上超过10秒后call.invoke会抛出异常的。假设后台很慢,每次都需要10秒,假设weblogic线程池大小为50,那么如果同时访问的人超过50个,或者每秒访问量超过5个,那么就会发生线程阻塞。这是系统性能问题,可以将weblogic的线程池最大数量设置高些来增加吞吐量。不过这种方式治标不治本,如果你的程序预计到并发访问量很大,那么后台响应超过1秒就不太合理了,这个改动起来就很麻烦了。