为什么HikariCP是性能最好的数据库连接池?

这世界上已经有了这么多的、开源的数据库连接池, 为什么要再写一个? 


   

1


   

 

这位老兄叫做Brett Wooldridge, 1989年毕业于新奥尔良洛约拉大学,计算机学士(你没看错,确实是1989年毕业的!),是一个生活在日本的美国人。 

Brett一直默默无闻,直到他推出了HikariCP。 

Hikari在日语中是“光”的意思,也就是说,这个连接池速度像“光”一样快。

HikariCP确实很快,在性能上碾压C3P0,DBCP2, Tomcat JDBC Pool 等一众连接池:

有了HikariCP这样耀眼的明星,就连BoneCP这样已经很快的连接池都不再维护了,它的作者“哀伤”说:BoneCP曾经击败过C3P0,DBCP这些老旧的连接池,但是为了支持HikariCP,可以放弃BoneCP了

现在已经有很多公司在使用HikariCP了,HikariCP还成为了SpringBoot默认的连接池,伴随着SpringBoot和微服务,HikariCP 必将迎来广泛的普及。      

2

HikariCP 是怎么来的呢? 

多年前,Brett 在开发一个产品原型,需要一个数据库连接池,像大多数开发人员一样,他Google了一个最流行的、最活跃的开源连接池。 

很不幸的是,在对原型产品做压力测试的时候,他遇到了死锁问题,一些Exception表明线程之间的连接状态丢失了。 

连接池是开源的,Brett把代码下载下来,试图找到并且Fix这些问题,然后贡献给社区。

但是当他开始阅读的时候,他发现这个连接池有几千行代码,远远超过他的预料。更要命的是有很多嵌套的锁,在一个地方获取,在很远的地方释放。在这样混乱的代码中,即使Fix了他遇到的问题,还有很多隐藏的问题难以预料。 

Brett换了一个连接池并且检查了代码,这次加锁的语义清晰了,但是代码量依然比他期待的多两倍,尤其是在把核心的连接池逻辑委托给另外一个库的情况下! 

Brett研究了更多的连接池,他发现这些连接池都以各种各样的方式违反了JDBC的规范和约定,例如当连接关闭,清除警告,回滚事务时,它们不会关闭Statements,不会重置用户更改的属性(如隔离级别),从而导致下一个消费者获得“脏连接”。 

他不仅“仰天长叹”:这是真的吗?这就是Java发展20年后,连接池的现状吗? 

程序员就是这样,遇到不爽的代码,还不如自己卷起袖子自己作一个, Talk is cheap ,show me the code ! 

这个连接池就是HikariCP,极致的性能让它拥有了良好的口碑,受到了越来越多用户的欢迎。

3

为什么HikariCP能这么快呢? 这要归功于Brett把事情做到极致的思路。 

Brett深入到了字节码级别,他研究了程序编译出的字节码,甚至JIT编译出的汇编,以便使得关键的代码例程小于JIT内联阈值,他简化了继承层次结构,隐藏了成员变量,消除了强制类型转换。 

他还做了很多微优化,其中一个就是不使用ArrayList,而是自己实现了一个叫FastList的类。因为ArrayList的get(int index)方法会对index做范围检查,而在HikariCP中,是可以确保index是合法的,范围检查是不必要的。

另外ArrayList 的remove(Object)方法会执行一个从头到尾的扫描,实际上JDBC的编程实践中在使用完Statement以后会马上关闭,或者以打开的相反次序来关闭,在这种情况下,从尾部扫描更好,于是ArrayList<Statement>被替换为自定义类FastList,这样就消除了这些额外开销。 

HikariCP 还提供了一个自定义的无锁的ConcurrentBag,实现了高度的并发和极端的低延迟。 

HikariCP 使用Javassist来生成Connection, Statement,和ResultSet的代理,在字节码中有getstatic 和invokevirtual 这样的指令,经过代码优化,它们被替换成了invokestatic ,这个指令更便于JVM去做更底层的优化。

这个优化甚至把栈帧中的栈深度从5降到了4,减少了push和pop指令。 

你看看,Brett可真是“锱铢必较”,榨干了每一个字节,这种精神好像在上世纪80年代,做DOS开发的程序员才可能拥有(Brett正好是89年毕业的),现在有了大容量的内存,更快的CPU,富裕了之后,大家已经忘记了曾经的窘境了。 

正是这样一点点微小的优化,凝聚溪流,汇集成河,让HikariCP获得了“光速的”性能,让人佩服,我估计后来者很难超越了吧。

参考资料:

Jooq对Brett的采访:

https://dzone.com/articles/jooq-tuesdays-what-it-takes-to-write-the-fastest-java-connection-pool

https://www.linkedin.com/in/brett-wooldridge-b6181b/ 

https://github.com/brettwooldridge/HikariCP-benchmark 

https://github.com/brettwooldridge/HikariCP/wiki/Down-the-Rabbit-Hole

https://github.com/brettwooldridge/HikariCP/issues/232

往期精彩回顾

我是一个线程

我是一个Java Class

面向对象圣经

函数式编程圣经

TCP/IP之大明邮差

CPU阿甘

我是一个网卡

我是一个路由器

一个故事讲完HTTPs

编程语言的巅峰

Java:一个帝国的诞生

JavaScript:一个屌丝的逆袭

负载均衡的原理

发布了443 篇原创文章 · 获赞 2773 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/coderising/article/details/103740234