<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          HikariCP為什么自己造了一個FastList?

          共 1749字,需瀏覽 4分鐘

           ·

          2020-11-18 03:54

          HikiriCP作為當(dāng)今世界上最快的數(shù)據(jù)庫連接池中間件,其對代碼追求的極致一直被開源愛好者津津樂道。HikariCP之所以這么快的其中一個原因就是:開發(fā)FastList取代ArrayList那么FastList是個什么東西?相比ArrayList有哪些出色的地方?接下來讓我們通過對源碼的分析來一探究竟。

          首先,讓我們打開HikariCP的源代碼,如果你不想下載它的源碼的話,你也可以只打開 https://github.com/brettwooldridge/HikariCP/blob/master/src/main/java/com/zaxxer/hikari/util/FastList.java 即可,就能看到FastList的源碼。

          我們首先看一下這個類的注釋,如下所示。通過這段注釋我們可以得出幾個結(jié)論,1. FastList并不是完全憑空造出來的而是基于ArrayList造出來的,正所謂站在巨人的肩膀上。2. 由這個類的注釋我們可知,它沒有range checking,即范圍檢查。如果看過ArrayList的源碼的話,我們就知道,它的get()、set()、remove()等很多方法中都執(zhí)行了范圍檢查(rangeCheck(index)):

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

          我們現(xiàn)在大概知道了FastList相比ArrayList的改進(jìn),下面列舉出兩個類具體對比如下表格所示:

          操作FastListArrayList
          add重寫支持
          get重寫支持
          removeLast支持不支持
          remove(Object)重寫支持
          clear重寫支持
          size一樣一樣
          isEmpty一樣一樣
          set重寫支持
          remove(int)重寫支持
          iterator重寫支持
          toArray、containsAll、contains、addAll、removeAll... ...throw new UnsupportedOperationException()支持

          精簡部分

          如上表格可知,F(xiàn)astList相比ArrayList,它屏蔽了很多它不需要的操作方法,例如:toArray、containsAll、contains、addAll、removeAll... ... 。只要調(diào)用這些方法,就會拋出UnsupportedOperationException異常。這是因為,F(xiàn)astList是HikariCP用來管理Statement(例如PrepareStatement)的,它并不需要這些方法。

          add

          add方法是一個非常有用、使用頻率很高的方法。而且剛才我們說了,HikariCP是用FastList用來管理Statement的,這就意味著,在我們使用拿出數(shù)據(jù)庫連接執(zhí)行SQL時,都需要創(chuàng)建Statement,這就需要調(diào)用FastList的add()方法,所以這個方法是一個非常高頻的方法。FastList的add()源碼如下。它和ArrayList最大的區(qū)別是,F(xiàn)astList假設(shè)大部分情況下不需要擴容,直接給數(shù)據(jù)最后一個元素賦值即可。而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?<??????@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相比還有一點不同,F(xiàn)astList需要擴容時,通過左移一位來實現(xiàn)成倍擴容(final int newCapacity = oldCapacity << 1),而ArrayList每次都是1.5倍擴容(int newCapacity = oldCapacity + (oldCapacity >> 1))。很明顯FastList的擴容少了一次+操作,性能更高。

          get&set&remove

          get也是使用頻率極高的一個方法,那么FastList做了哪些優(yōu)化了,請看源碼。優(yōu)化的地方非常清楚了,F(xiàn)astList假定絕大部分調(diào)用get方法的index是合法的,從而不進(jìn)行范圍檢查。而ArrayList則需要先進(jìn)行范圍檢查,再獲取具體位置的值。我們知道:無論什么語言編寫的多么高性能的代碼,只要有代碼執(zhí)行,就會有性能損耗。這也是FastList干掉范圍檢查的原因,能快一點是一點:

          /**
          ?*?@return?the?element,?or?ArrayIndexOutOfBounds?is?thrown?if?the?index?is?invalid
          ?*/
          @Override
          public?T?get(int?index)
          {
          ???//?ArrayList需要先調(diào)用rangeCheck(index)進(jìn)行范圍檢查
          ???return?elementData[index];
          }

          set方法以及remove(int)方法和get方法進(jìn)行了完全一樣的優(yōu)化,去掉了范圍檢查,它們都假定操作的index是完全合法的,只要每次操作的index完全有效,那么范圍檢查就是多余的,就可以通過干掉范圍檢查來提高性能。

          removeLast

          這是FastList新增的一個方法,ArrayList是沒有這個方法的。為什么HikariCP新增了一個這樣的方法呢?我們知道,在獲取數(shù)據(jù)庫連接執(zhí)行SQL時,如果創(chuàng)建了多個Statement,那么后創(chuàng)建的Statement需要先關(guān)閉。以3個Statement為例,我們依次創(chuàng)建了stmt1,stmt2,stmt3。那么良好的編程習(xí)慣是先執(zhí)行stmt3.close(),再stmt2.close(),最后stmt1.close()。而HikiriCP是用FastList管理Statement這個過程中實際調(diào)用了3次add()方法,然后依次調(diào)用3次removeLast方法,這就是為什么HikariCP需要造一個removeList方法的原因:

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

          size&isEmpty

          這兩個方法FastList都沒有進(jìn)行任何優(yōu)化,和ArrayList是一樣的。

          總結(jié)

          現(xiàn)在知道HikariCP為什么要這樣做了吧?這是因為,HikariCP的FastList和JDK中的ArrayList定位不一樣,ArrayList是提供給無數(shù)使用JDK的用戶使用的,所以,它的使用環(huán)境非常惡劣,那么它必須做各種合法性的檢查。而FastList是HikariCP用來管理Statement的,是給它自己使用的,是特定場景下為了性能極致優(yōu)化而造出來的一個東西,它只適用于這樣特定的場景。


          DD自研的滬牌代拍業(yè)務(wù),點擊直達(dá)


          往期推薦

          Spring Boot 2.4.0 正式發(fā)布!全新的配置處理機制,擁抱云原生!

          服務(wù)網(wǎng)格仍然很難

          10道棘手的Java面試題,看看你能答對幾個?

          如果MySQL磁盤滿了,會發(fā)生什么?

          Mysql 都會遭受哪些方面的攻擊?

          Git 提交代碼之后的幾種后悔藥


          掃一掃,關(guān)注我

          一起學(xué)習(xí),一起進(jìn)步

          每周贈書,福利不斷

          深度內(nèi)容

          推薦加入





          瀏覽 79
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  九一福利视频 | 国产毛片毛片毛片 | 久久99免费视频 | 亚洲午夜精品久久久 | 三级片网站视频 |