分析springboot2.0自带连接池HikariCP的优势

HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池,是一个高性能的JDBC连接池,基于BoneCP做了不少的改进和优化。其作者还有另外一个开源作品——高性能的JSON解析器HikariJSON。

分析springboot2.0自带连接池HikariCP的优势_第1张图片

 

从以上图可看出Hikari相比起其它连接池的性能高了非常多,那么,这么好的是怎么做到的呢?官网详细地说明了HikariCP所做的一些优化,总结如下:

  • 字节码精简 :优化代码,直到编译后的字节码最少,这样,CPU缓存可以加载更多的程序代码;
  • 优化代理和拦截器:减少代码,例如HikariCP的Statement proxy只有100行代码,只有BoneCP的十分之一;
  • 自定义数组类型(FastStatementList)代替ArrayList:避免每次get()调用都要进行range check,避免调用remove()时的从头到尾的扫描(由于连接的特点是后获取连接的先释放);
  • 自定义集合类型(ConcurrentBag:提高并发读写的效率;
  • 其他针对BoneCP缺陷的优化,比如对于耗时超过一个CPU时间片的方法调用的研究。

 

1、代码量精简比较:

分析springboot2.0自带连接池HikariCP的优势_第2张图片

2、第三方关于速度的测试:

分析springboot2.0自带连接池HikariCP的优势_第3张图片

3、软件稳定性

分析springboot2.0自带连接池HikariCP的优势_第4张图片

4、可靠性

另外,关于可靠性方面,也是有实验和数据支持的。对于数据库连接中断的情况,通过测试getConnection(),各种CP的不相同处理方法如下:

(所有CP都配置了跟connectionTimeout类似的参数为5秒钟)

  • HikariCP:等待5秒钟后,如果连接还是没有恢复,则抛出一个SQLExceptions 异常;后续的getConnection()也是一样处理;
  • C3P0:完全没有反应,没有提示,也不会在“CheckoutTimeout”配置的时长超时后有任何通知给调用者;然后等待2分钟后终于醒来了,返回一个error;
  • Tomcat:返回一个connection,然后……调用者如果利用这个无效的connection执行SQL语句……结果可想而知;大约55秒之后终于醒来了,这时候的getConnection()终于可以返回一个error,但没有等待参数配置的5秒钟,而是立即返回error;
  • BoneCP:跟Tomcat的处理方法一样;也是大约55秒之后才醒来,有了正常的反应,并且终于会等待5秒钟之后返回error了;

5、HikariCP源代码分析

1、首先,HikariCP利用了一个第三方的Java字节码修改类库Javassist来生成委托实现动态代理。动态代理的实现在ProxyFactory类之所以使用Javassist生成动态代理,是因为其速度更快,相比于JDK Proxy生成的字节码更少,精简了很多不必要的字节码。

代理工厂类

分析springboot2.0自带连接池HikariCP的优势_第5张图片

分析springboot2.0自带连接池HikariCP的优势_第6张图片

分析springboot2.0自带连接池HikariCP的优势_第7张图片

 

2、其次,单独写了一个并发类-ConcurrentBag,ConcurrentBag的实现借鉴于C#中的同名类,是一个专门为连接池设计的lock-less集合,实现了比LinkedBlockingQueue、LinkedTransferQueue更好的并发性能。

ConcurrentBag类

分析springboot2.0自带连接池HikariCP的优势_第8张图片

ProxyConnection代理连接类

分析springboot2.0自带连接池HikariCP的优势_第9张图片

ConcurrentBag内部同时使用了ThreadLocal和CopyOnWriteArrayList来存储元素,其中CopyOnWriteArrayList是线程共享的。ConcurrentBag采用了queue-stealing的机制获取元素:首先尝试从ThreadLocal中获取属于当前线程的元素来避免锁竞争,如果没有可用元素则再次从共享的CopyOnWriteArrayList中获取。此外,ThreadLocal和CopyOnWriteArrayList在ConcurrentBag中都是成员变量,线程间不共享,避免了伪共享(false sharing)的发生

3、使用FastList替代ArrayList

1、FastList是一个List接口的精简实现,只实现了接口中必要的几个方法。

分析springboot2.0自带连接池HikariCP的优势_第10张图片

2、JDK ArrayList每次调用get()方法时都会进行rangeCheck检查索引是否越界,FastList的实现中去除了这一检查,只要保证索引合法那么rangeCheck就成为了不必要的计算开销(当然开销极小)。

分析springboot2.0自带连接池HikariCP的优势_第11张图片

3、此外,HikariCP使用List来保存打开的Statement,当Statement关闭或Connection关闭时需要将对应的Statement从List中移除。通常情况下,同一个Connection创建了多个Statement时,后打开的Statement会先关闭。ArrayList的remove(Object)方法是从头开始遍历数组,而FastList是从数组的尾部开始遍历,因此更为高效。

分析springboot2.0自带连接池HikariCP的优势_第12张图片

你可能感兴趣的:(j2ee)