Skip to content

High Performance Utils

Calvin Xiao edited this page Apr 28, 2017 · 2 revisions

1. Overview

库的设计目标,是把最佳实践都封装起来,让大家使用类库时,默认就获得最优的性能。

2. 日期

2.1 DateFormatUtil

日期与String相互转换时,JDK的SimpleDateFormat,又慢,又非线程安全。

在不能全面转为Joda Time时,使用Common Lang的FastDateFormat,又快,又线程安全,还能缓存实例。

2.2 CachingDateFormatter

FastDateFormat再快,日期格式化还是个消耗很大的事情。

参考Logback和Log4j2,在打印当前时间的场景里,将同一时刻的结果缓存。

3. 文本

3.1 StringBuilderHolder

ThreadLocal地重用StringBuilder,节约长字符串拼接时的内存消耗,节约成倍复制扩容的CPU消耗,是OpenHFT等好几个类库的共同选择。

3.2 HashUtil

ThreadLocal地重用SHA1的MessageDiggest,减少每次创建MessageDigest的消耗,也是Tomcat,Facebook等好几个类库的共同选择。

3.3 JsonMapper

封装Jackson的实现,并提供不序列化“值为NULL的属性”等选择。

3.4 TextValidator

判断是否合法的电话,身份证之类的正则表达式校验,Pattern必须得预先编译而不要每次创建,但总有匆忙的同学忘记这点。

3.5 MoreStringUtil

Common Lang的StringUtils已经很好用了。不过字符串操作的消耗总是很大,这里针对一些操作,给出更极致的性能优化,比如split()。

4. 集合

4.1 原子类型集合

当集合中的元素是原子类型,而不是对象的时候。直接以原子类型来存储,不但节约内存(int vs Integer, 4 bytes vs 16 bytes),甚至内部的数据结构也能完全不一样,从而大幅提高性能。

从Netty中移植了IntOjbectHashMap 和 LongObjectHashMap,性能约提升50%。后面还会有IntArrayList等等。

4.2 MapUtil, ListUtil ...

各种集合类的Util的创建函数,强迫大家去思考Array Base 集合类的初始大小,避免了容量不足时的成倍扩容; HashMap的加载因子,减少哈希冲突。

在集合为空或只有一个元素时,使用Java Collections的特殊数据结构,进一步节约内存。

4.3 其他性能相关扩展类型

  • Guava AtomicLongMap :as MapCounter,不用再自己处理“如果有就+1,没有就放个元素进去”的烦事
  • Guava WeakConcurrentHashMap: 键值为弱引用的并发Map,只此一家
  • MUtableLong等值类型,避免重新创建Long/Integer对象并放入Map中。

5. 并发

5.1 JSR166e

JDK的不同版本,不断推出性能更优的并发实现,但如果考虑多JDK版本到的兼容就让人发愁了。好在有Doug Lea大神的JSR166e项目。

1. ThreadLocalRandom

Random本身有全局锁,JDK7的ThreadLocalRandom通过在ThreadLocal里放Random避免了锁。

2. LongAdder

作为计数器,AtomicLong虽然能通过CAS避免锁,但如果线程竞争激烈时依然有很大的损耗。JDK8的LongAdder,根据并发情况,将计数器智能的拆开成若干个,等取值时再求和。

3. ConcurrentHashMapV8

JDK5开始的ConcurrentHashMap是经典的分散锁模式,而JDK8的ConcurrentHashMap,优化后居然取消了锁。

5.2 ThreadPoolBuilder

比JDK Executors,提供更好的线程池设置,比如FixedPool的队列最大长度,CachedPool的最大线程数等。

另提供一个从Tomcat移植的QueueableCachedPool,“支持可变的线程数,跑满线程时任务放队列”这种符合大家想想的场景。

5.3 ThreadLocalContext

提供ThreadLocal HashMap存放上下文的示例,并给出更高效的,使用EnumMap的建议。

6. 反射

6.1 BeanMapper

基于orika封装,同时避免了一些低效API的使用,比如不给出来源集合的类型,让框架自己去反射"iterator"函数的返回值来获取类型的恶劣行为。

更给出了预生成Type类型的最高效的用法。

6.2 FastMethodInvoker

基于cglib,通过代码生成实现最快速的反射调用。比如反射调用A类的“hello” 方法,它就直接生成一个调用a.hello()的FastMethod子类.

7. 其他

7.1 ExceptionUtil

异常构造时,获取当前Stack Trace是一个很耗时的过程,把Stack Trace打印也同样消耗。 如果是一个比较清楚出处的异常,可以通过static定义的静态异常。 但如果异常的message会变化,就不能静态定义唯一的异常了,此时可使用克隆异常,依然避过构造函数。

7.2 SystemPropertiesUtil

Properties本质上是一个有锁的HashTable,所以不能频繁的调用System.getProperty()。提供了一个以回调方式获取变化的ListenableProperties。