第三章 Java 字串處理加速器設計
3.5 Hardware Native Interface
3.5.5 其它使用 arraycopy、indexOf 加速器之 methods
雖然兩個字串加速器之命名是以兩個高度相關的 method 名稱來命名,但不代 表這兩個加速器只能使用在這兩個 method 或 overloading 之 methods 上。由於 indexOf 加速器具有字元搜尋與字元比較之操作,陣列操作只要有搜尋或是比較 操作,且元素大小是大於等於 2-byte,都有機會使用 indexOf 加速器增進效能。
而本小節將介紹如何使用兩個加速器來加速 Java String Class 中的 equals()和 replace()兩個 methods。
在 JAIP 平台中實作 String.equals(String str) method 有三種方法,第一種是使 用 c function 實作之 native method,此介面雖然廣泛在各種 JVM 上來加速,但由 於 JAIP 若要使用 c function 定義的 native binary,需透過 IPC 介面傳送 interrupt 訊號到 RISC-core 上,此 overhead 不但沒有達成加速目的,反而降低程式效能。
第二種方法便是直接使用 Java 程式碼實作。透過 Java 程式碼撰寫迴圈程式,每 個 iteration 都被 javac compiler 編譯成為 caload 與 ifeq 等 Java bytecode,逐一比對 字元是否相同。若要達到更有效率的比對操作,可以直接實作一個 equals 專用加 速電路並使用 hardware native interface 來呼叫 method。但考量到 indexOf 加速電 路已有高度相關操作,我們重複使用此加速電路。String.equals(String str)設計如 圖 23 所示,首先檢查兩個字串物件之 reference 是否相等,若是相等,代表兩個 字串是同一個 object instance,不需要進行字元陣列的比對,直接 return “true”。
ptnPfx_valid = 01 ptnPfx_valid = 11
t
0t
1若兩個 string object 不相等,這時候可能需要比對字元陣列才會知道是否 equals。
比對字元陣列之前,先檢查兩個字串長度是否一致,若不一致,我們可以肯定兩 個字串一定不相等。此 method 最為關鍵的地方在於字元陣列的比對。若兩個長度 相等的字元陣列相符,使用 indexOf method 一定會回傳 0,因為兩個字串值在 index 等於 0 的地方互為子字串。由於 indexOf 加速器在字串比對上使用一個 word 當作 單位,而第二種方法是使用單一字元為比較單位。因此,理想上此方法會比第二 種方法快了兩倍。
圖 23 使用 indexOf 加速器實作 String.equals(String str)之流程圖
return true start
Is both string reference
equal?
Is both string count equal?
Is i == 0?
i = this.indexOf(str) yes
no
yes
no
yes
no
return false
42
圖 24 使用 indexOf 與 arraycopy 加速器實作 string.replace()之流程圖
另一個使用字串加速器的 method 為 string.replace(char oldChar, char newChar)。
此 method 是在一個 string object 內搜尋由 programmer 輸入的一個字元─oldChar,
所有出現位置,並將之取代為另一個輸入的新字元─newChar。若位搜尋到符合 的字元,直接回傳 string 本身;若至少一個 oldChar 被找到,宣告新的 string object 存放取代後的字元陣列,並回傳之。應用之案例如:當程式解析使用者輸入的檔 案路徑、class path 或 URL 時,replace method 可以找尋其路徑的 separator,並取 代 成 為 系 統 內 部 使 用 的 正 規 separator , 例 如 Java class loader 可 能 會 使 用
i = this.indexOf(oldChar, 0)
Is i == -1
Use System.arraycopy copy prefix to new_buf[]
Is i < len
i = this.indexOf(oldChar, i + 1)
Is i == -1 System.arraycopy() Use
copy the chars from (last_i + 1) to
(i – 1)
Use System.arraycopy copy the remaining chars
Use the new_buf[] array as an instance to new a string
object return the new string new_buf[i] = newChar
no
取代的字元出現,直接將 newChar 寫進原本之位置。兩個加速器可以應用的地方 在於 oldChar 之搜尋,以及 oldChar 未出現之字串片段複製動作。其完整流程如圖 24 所示。