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

首先,让我们打开HikariCP的源代码,如果你不想下载它的源码的话,你也可以只打开 https://github.com/brettwooldridge/HikariCP/blob/master/src/main/java/com/zaxxer/hikari/util/FastList.java 即可,就能看到FastList的源码。

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

/*** 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)的,它并不需要这些方法。

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 codefinal 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干掉范围检查的原因,能快一点是一点:

/*** @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 提交代码之后的几种后悔药

扫一扫,关注我

一起学习,一起进步

每周赠书,福利不断

深度内容

推荐加入

HikariCP为什么自己造了一个FastList?相关推荐

  1. 干掉ArrayList:HikariCP为什么自己造了一个FastList?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! HikiriCP作为当今世界上最快的数据库连接池中间件,其 ...

  2. python数据校验_最近抽空造了一个数据校验的轮子 Python -validator

    最近抽空造了一个数据校验的轮子 python-validator. 在开发 web 应用时,经常需要校验前端传入的数据.如果使用 Django,那么可以使用自带的 forms 进行数据校验. pyth ...

  3. 用php造了一个地址自动识别功能

    用php造了一个地址自动识别功能 地址自动识别现在普遍,特别是用在快递填写地址,姓名,手机号码的时候,会把这些按照一定的规范填写后,点击自动识别后,会自动填写到各自的input.最近也简单的实现了这个 ...

  4. 转型下沉的51talk 能否在在线教育“造”出一个拼多多?

    51talk自上市以来,一直处于亏损当中,但12月9日公布的财报显示,主营菲教一对一业务的似乎为其带来了新看点. 数据显示,1对1业务首次实现Non-GAAP盈利,其Non-GAAP净利润为270万, ...

  5. 从零造的一个网络轮子

    从零造的一个网络轮子 序 大概是一些碎碎念 一 类图及各类简述 二 各个类详述及部分代码   2.1.main() & FairySunOfNetBaseStart() & Fairy ...

  6. 【AI简报20220211期】硬核UP主自己造了一个激光雷达、详解AI加速器

    嵌入式AI 详解AI加速器(一):2012年的AlexNet到底做对了什么? 原文: https://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==&mid ...

  7. 真正的全栈工程师!B站硬核UP主自己造了一个激光雷达

    机器之心报道 机器之心编辑部 转载自:机器之心 从零造一个激光雷达,需要多久? 激光雷达(LiDAR)是激光探测及测距系统的简称,目前广泛应用在无人驾驶和扫地机器人等领域.这种广泛的应用一方面得益于激 ...

  8. 苏宁不蹭618,造了一个“宝宝节”

    6月1日凌晨1点,苏宁易购六一宝宝节开心直播夜全网观看量破1.6亿,这一"宝宝节"为当下电商平台的营销方式带来怎样的思考? 如今,双十一.618.818等促销节点已经列入到人们一年 ...

  9. 下沉市场中的元宇宙:我们造了一个“虚拟贫民窟”?

    "web2.0的时候,我们追求资讯共享.跨越地域和种族的交流,web3.0的时候,我们发行货币,模拟娱乐,复制一个消费至死的地球,你们管这堆虚拟世界的玩具叫元宇宙?"  在探访元宇 ...

最新文章

  1. 一文读懂生物医学领域的传感器
  2. MySQL第1天:整体目录
  3. GitHub如何删除一个repository(仓库)
  4. 六十、第一个SpringBoot的 helloworld程序
  5. 阿里巴巴港股股价创历史新高 市值超6.1万亿港元
  6. 【Kafka】Kafka 使用传统的 avro API 自定义序列化类和反序列化类
  7. @扎克伯格:一句对不起,能挽回我们泄漏的数据吗?
  8. HDU2032 杨辉三角【入门】
  9. 如何在 Mac 上阻止 FaceTime 通话和 iMessage 信息?
  10. vmware安装安卓android详教程,虚拟机安装安卓系统教程
  11. 【装修大营救】装修失误郁闷到要吐血、追悔莫及:水电改、刷墙、橱柜
  12. 美国生活第二个月照片(2)
  13. 到底什么是类脑计算?
  14. elasticsearch查询之图书智能推荐
  15. Windows下安装pycocotools(本人亲测,可以解决)
  16. 一遍两遍三四遍,知识含义清晰现
  17. ARAP重分类:扪心自问,细节处你真的懂我吗?
  18. linux玩大型游戏下载软件,5个最受欢迎Linux版大型FPS游戏
  19. 上海腾科教育干货分享之达梦数据库培训课程DCP
  20. 《地球毁灭日》5希望号诺亚方舟

热门文章

  1. 自定义的GridView控件源代码
  2. Linux系统中FTP的配置(图文详解-全)
  3. linux centos 使用 alpine 编译的二进制文件 报错 /lib/ld-musl-x86_64.so.1: bad ELF interpreter 解决方法
  4. linux centos7 开机自动登录
  5. pycharm 远程调试
  6. linux 64平台上编译32位程序: GCC编译选项 -m64 -m32 -mx32
  7. shell公共函数:/etc/init.d/functions
  8. 深度学习与计算机视觉系列(4)_最优化与随机梯度下降\数据预处理,正则化与损失函数
  9. mysql 5.5 5.6差异,MySQL5.5和MySQL5.6授权区别
  10. php 输出 cvs,php将数组转换成cvs格式并输出的简单示例