HikariCP为何本身造了一个FastList?

HikiriCP做为当今世界上最快的数据库链接池中间件,其对代码追求的极致一直被开源爱好者津津乐道。HikariCP之因此这么快的其中一个缘由就是:开发FastList取代ArrayList。那么FastList是个什么东西?相比ArrayList有哪些出色的地方?接下来让咱们经过对源码的分析来一探究竟。java

首先,让咱们打开HikariCP的源代码,若是你不想下载它的源码的话,你也能够只打开 https://github.com/brettwooldridge/HikariCP/blob/master/src/main/java/com/zaxxer/hikari/util/FastList.java 便可,就能看到FastList的源码。git

咱们首先看一下这个类的注释,以下所示。经过这段注释咱们能够得出几个结论,1. FastList并非彻底凭空造出来的而是基于ArrayList造出来的,正所谓站在巨人的肩膀上。2. 由这个类的注释咱们可知,它没有range checking,即范围检查。若是看过ArrayList的源码的话,咱们就知道,它的get()、set()、remove()等不少方法中都执行了范围检查(rangeCheck(index)):github

/**
 * Fast list without range checking.
 *
 * @author Brett Wooldridge
 */
public final class FastList<T> extends ArrayList<T>
{
   ... ...
}

咱们如今大概知道了FastList相比ArrayList的改进,下面列举出两个类具体对好比下表格所示:面试

 

操做 FastList ArrayList
add 重写 支持
get 重写 支持
removeLast 支持 不支持
remove(Object) 重写 支持
clear 重写 支持
size 同样 同样
isEmpty 同样 同样
set 重写 支持
remove(int) 重写 支持
iterator 重写 支持
toArray、containsAll、contains、addAll、removeAll... ... throw new UnsupportedOperationException() 支持

 

精简部分

如上表格可知,FastList相比ArrayList,它屏蔽了不少它不须要的操做方法,例如:toArray、containsAll、contains、addAll、removeAll... ... 。只要调用这些方法,就会抛出UnsupportedOperationException异常。这是由于,FastList是HikariCP用来管理Statement(例如PrepareStatement)的,它并不须要这些方法。sql

add

add方法是一个很是有用、使用频率很高的方法。并且刚才咱们说了,HikariCP是用FastList用来管理Statement的,这就意味着,在咱们使用拿出数据库链接执行SQL时,都须要建立Statement,这就须要调用FastList的add()方法,因此这个方法是一个很是高频的方法。FastList的add()源码以下。它和ArrayList最大的区别是,FastList假设大部分状况下不须要扩容,直接给数据最后一个元素赋值便可。而ArrayList偏偏相反,须要先确保容量足够:数据库

public boolean add(T element)
{
   try {
      elementData[size++] = element;
   }
   catch (ArrayIndexOutOfBoundsException e) {
      // overflow-conscious code
      final int oldCapacity = elementData.length;
      final int newCapacity = oldCapacity << 1;
      @SuppressWarnings("unchecked")
      final T[] newElementData = (T[]) Array.newInstance(clazz, newCapacity);
      System.arraycopy(elementData, 0, newElementData, 0, oldCapacity);
      newElementData[size - 1] = element;
      elementData = newElementData;     
   }
   return true;
}

FastList的add方法与ArrayList相比还有一点不一样,FastList须要扩容时,经过左移一位来实现成倍扩容(final int newCapacity = oldCapacity << 1),而ArrayList每次都是1.5倍扩容(int newCapacity = oldCapacity + (oldCapacity >> 1))。很明显FastList的扩容少了一次+操做,性能更高。编程

get&set&remove

get也是使用频率极高的一个方法,那么FastList作了哪些优化了,请看源码。优化的地方很是清楚了,FastList假定绝大部分调用get方法的index是合法的,从而不进行范围检查。而ArrayList则须要先进行范围检查,再获取具体位置的值。咱们知道:不管什么语言编写的多么高性能的代码,只要有代码执行,就会有性能损耗。这也是FastList干掉范围检查的缘由,能快一点是一点:ide

/**
 * @return the element, or ArrayIndexOutOfBounds is thrown if the index is invalid
 */
@Override
public T get(int index)
{
   // ArrayList须要先调用rangeCheck(index)进行范围检查
   return elementData[index];
}

set方法以及remove(int)方法和get方法进行了彻底同样的优化,去掉了范围检查,它们都假定操做的index是彻底合法的,只要每次操做的index彻底有效,那么范围检查就是多余的,就能够经过干掉范围检查来提升性能。性能

removeLast

这是FastList新增的一个方法,ArrayList是没有这个方法的。为何HikariCP新增了一个这样的方法呢?咱们知道,在获取数据库链接执行SQL时,若是建立了多个Statement,那么后建立的Statement须要先关闭。以3个Statement为例,咱们依次建立了stmt1,stmt2,stmt3。那么良好的编程习惯是先执行stmt3.close(),再stmt2.close(),最后stmt1.close()。而HikiriCP是用FastList管理Statement这个过程当中实际调用了3次add()方法,而后依次调用3次removeLast方法,这就是为何HikariCP须要造一个removeList方法的缘由:优化

public T removeLast()
{
   T element = elementData[--size];
   elementData[size] = null;
   return element;
}
size&isEmpty

这两个方法FastList都没有进行任何优化,和ArrayList是同样的。

总结

如今知道HikariCP为何要这样作了吧?这是由于,HikariCP的FastList和JDK中的ArrayList定位不同,ArrayList是提供给无数使用JDK的用户使用的,因此,它的使用环境很是恶劣,那么它必须作各类合法性的检查。而FastList是HikariCP用来管理Statement的,是给它本身使用的,是特定场景下为了性能极致优化而造出来的一个东西,它只适用于这样特定的场景。

DD自研的沪牌代拍业务,点击直达

往期推荐

Spring Boot 2.4.0 正式发布!全新的配置处理机制,拥抱云原生!

服务网格仍然很难

10道棘手的Java面试题,看看你能答对几个?

若是MySQL磁盘满了,会发生什么?

Mysql 都会遭受哪些方面的***?

Git 提交代码以后的几种后悔药

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相关文章
相关标签/搜索