性能优化对程序员来说太过稀疏平常,无论是前端,还是后端,无论是单点应用,还是分布系统,都无法脱离性能优化。性能优化简单理解是在不影响系统正常运行的前提下缩短运行时间。
关于性能优化,你知道这三个原则吗?
以数据为性能优化前提,忌过早过度优化。
爱德华兹·戴明说:“除了上帝,任何人都必须用数据说话。” 学会用数据说话、用数据决策、用数据管理,开展性能优化工作时不应凭空猜测,而应有理有据。像系统性能开了小差,可能受制于CPU、IO,也可能是内存问题。
Donald Knuth曾说:“premature optimization is the root of all evil.”即“过早优化是万恶之源。”要知道让程序运行快一点再快一点比让快速运行的程序正确容易很多。就比如很多女生嚷嚷着要减肥,各种装备都买好了,但减肥大业却一直停滞在准备阶段。过早优化就好像把大量精力放在不重要的问题上,而忽略问题本质。
《论语·先进》 子贡问:“师与商也孰贤?”
子曰:“师也过,商也不及。”
曰:“然则师愈与?”
子曰:“过犹不及。”
过犹不及,事缓则圆。在性能优化方面,无需过于苛求,保证达到预期即可。
Java性能优化不知道困扰了多少程序员,因为供给程序利用的资源有限,如何让程序在利用最少资源的前提下完成预定任务,成为困扰从业者的常见问题。
Java性能优化要点:
科学使用单例和静态变量。单例模式作为Java最常见最简单的设计模式,它的核心结构中只包含一个被称为单例的特殊类,它保证系统中应用模式一个类只有一个实例。注意单例模式的三个要点:某个类只能是一个实例;它必须自行创建实例;它必须自行向整个系统提供这个实例。使用单例虽能减轻加载负担,提高效率,但并不是所有地方都适用,Java程序员多将其用于控制资源使用、控制数据共享、控制实例产生方面,以达到节省资源,提高工作效率,缩短加载时间的目的。
静态变量(Static Variable)在计算机编程领域指在程序执行前系统就为之静态分配(也即在运行时中不再改变分配情况)存储空间的一类变量。它是与程序有着相同生命周期的变量,但不可随意使用,像如果某对象被定义为static变量引用时Java垃圾回收机制无法回收该对象所占内存。
使用局部变量。局部变量指形参、方法内定义的变量及代码块中定义的变量。局部变量存储在“栈中”,生命周期与所在区域保持一致,而成员变量存储于“堆中”,生命周期与对象保持一致,静态变量存储在“方法区的静态区”,生命周期与所对应的的类保持一致,速度较之局部变量较慢。
减少对变量的重复计算和不必要创建。众所周知,在循环中循环条件多被反复计算,避开复杂表达式,保证循环条件值不变,可加快程序运行速度。创建附加对象,提高程序功能,虽是好事,但不必要对象创建只会破坏程序风格,降低其性能。
使用final修饰符。final多用来修饰类、方法和变量。修饰类,类不能被继承;修饰方法,方法不能被重写;修饰变量,变量不能被重新赋值。JAVA核心API中很多使用final,编译器会巧妙内联final方法,提高性能。
尽可能少使用finalize方法,使用finalize清理资源会加重GC负担,降低程序运行效率。
尽可能避开过多常地创建Java对象。如果在常地创建新对象,系统不仅要耗费时间创建对象,同时要对其进行处理和垃圾回收,为提高程序性能可以选择用数据替代对象。
合理创建hashMap,创建并最大程度利用hashMap,可以规避hashMap对hash的多次重构,减少性能损耗。
借助“移位”替代‘a/b’和‘a*b’。使用“移位”替代‘a/b’操作可以降低“/”和“*”的代价,提高Java性能,但记得加注释,提高可读性。
尽早释放无用对象引用,方法局部引用变量所引用的对象多随方法终结化为垃圾,需要及时释放,以减少对程序的消耗。
尽可能避免使用split和二维数组。Split因支持正则表达式,效率低下,而二维数组占据内存巨大,因此除非必须使用,尽量少用。
尽可能确定StringBuffer容量,在创建StringBuffer时指定大小,谨防内存不够的自动增长,提高程序性能。
System.arraycopy ()速度远快于循环复制数组,小伙伴可以选择使用System.arraycopy ()替代循环复制数组。
尽可能缓存常用对象,使用EhCache和Oscache缓存常使用对象可缓解因系统占用过多内存导致的性能下降问题。
合理使用java.util.Vector。Vector虽与StringBuffer类似,但扩容时需把现有元素赋值到新的存储空间,影响性能。
科学使用array和ArrayList。Array数组效率高,容量固定,无法动态改变。但ArrayList容量可动态增长,但效率较低。小伙伴可根据自己需要选择性使用。
此外,使用基本数据类型替代对象,科学使用HashMap、ArrayList、尽可能规避大内存分配,尽可能重用对象、尽可能在finally块中释放资源、不可重复初始化变量、不用new关键词创建对象实例、慎用异常等操作均可优化性能。今天的知识点,你学会了吗?
读书不觉已春深,一寸光阴一寸金。