2
High Performance Utils
Calvin Xiao edited this page 2017-04-28 13:39:05 +08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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。