java的优化是一个大的课题,恐怕一本书都写不完,随着版本技术的更新优化问题越来越重要了,我今天就讲讲比较重要的5大优化。
代码优化的目标是:
1、减小代码的体积
2、提高代码运行的效率
要对你的 Java 代码进行优化,需要理解 java 不同要素之间的相互作用,以及它是如何与其运行时的操作系统进行交互的。
在我们开始之前, 你也许会担心许可的问题. Java 为 Oracle 公司所有,遵循 Oracle 的 BCL 许可,该许可证不是一个免费/开源许可证。即便如此, 仍然有许多开源项目由 Oracle 公司的 Java 开发。 OpenJDK 是 java 平台自由软件的实现,遵循 GPL v2 许可。 (更多信息请参见维基百科 Free Java implementations。)
让我们开始吧
性能优化取决于多个因素,包括垃圾收集、虚拟机和底层操作系统(OS)设置。有多个工具可供开发人员进行分析和优化时使用,你可以通过阅读 Java Tools for Source Code Optimization and Analysis 来学习和使用它们。如果你正苦苦挣扎于术语和 Java 的原理,可以先去查看 Livecoding Java category page,上面有直播,存档的视频,以及一些其他有用的信息。
“视情况而定”
必须要明白的是,没有两个应用程序可以使用相同的优化方式,也没有完美的优化 java 应用程序的参考路径。使用最佳实践并且坚持采用适当的方式处理性能优化。想要达到真正最高的性能优化,你作为一个 Java 开发人员,需要对 Java 虚拟机(JVM)和底层操作系统有正确的理解:
JVM 和底层操作系统:Java 虚拟机是任何 Java 程序的家。阅读 JVM internals guide 了解更多有关于 JVM 内部和操作系统差异的内容。
JVM 分布模型:Java 分布模型为您的应用程序处理多个JVM实例。分布模型提高了应用程序的性能,因为它获得更多的资源来工作。你可以用两种方法继续优化。第一种方法是在一个堆大小为2GB或8GB的单服务器运行多个 JVM。第二种方法是在多个服务器上运行单个 JVM。正确方法的选择取决于多个因素,包括可用性和响应性。
JVM 体系结构:选择正确的 JVM 体系结构对于性能来说是很重要的。你可以选择 64 位或者 32 位的 JVM 机器。 一般来说,32 位 JVM 的性能比它对应的 64 位 JVM 要好。 只有当你需要的堆大小大于 3 GB 时,才选择 64 位的 JVM。
清楚了性能优化和其要素,现在我们可以专注于那些可以优化你的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作为代替.
远离递归.递归会占用大量资源!
在一些需要表达式来处理字符串的地方,可以采用以下方式来优化表达式:
1关注如何让匹配快速失败:正则表达式慢的原因通常是匹配失败的过程慢,而不是匹配成功的过程慢;
2正则表达式以简单、必需的字元开始:一个正则表达式的起始标记应当尽可能快速地测试并排除明显不匹配的位置;
3使用量词模式,使它们后面的字元互斥:当字符与字元相邻或者子表达式能够重叠匹配时,正则表达式尝试拆解文本的路径数量增加,为了避免这种情况,尽量具体化匹配模式;
4减少分支数量,缩小分支范围:分支可能要求在字符串的每一个位置上测试所有分支选项,可以通过使用字符集和选项组来减少对分支的需求,或者将分支在正则表达式上的位置推后。
5使用非捕获组:捕获组消耗时间和内存来记录反向引用,并使它保存最新。如果你不需要一个反向引用,可以使用非捕获组来避免这些开销,比如用(?:...)来替代(...)。
6只捕获感兴趣的文本以减少后处理:如果你需要引用匹配的部分,应该采取一切手段捕获哪些片段,再使用反向引用来处理。
7暴露必须的字元:帮助正则表达式引擎在查询优化过程时做出明智的决策,可以尝试让它更容易地判断哪些字元是必须的。
8使用合适的量词;
9把正则表达式赋值给变量并重用它们;
10将复杂的正则表达式拆分为简单的片段:避免在一个正则表达式中处理太多的任务。
关于跟多的实战优化《大话JAVA性能优化》《高性能 JavaScript》 这两本书大家可以去看看
java的性能优化可是一个大课题, 藉着这片文章抛砖引玉。文章肯定还有不够完整的地方,希望各位读友在评论中发表自己的观点
对于小白可以去看看https://ke.qq.com/course/225121#tuin=6734be20每天晚上会有技术分享,里面比较适合,经验较少也可以去看看,实战才是检验成果的,那的实操经验丰富希望对刚入行的朋友有帮助
网友评论