- 適用於 JDK 23 的 GraalVM (最新版)
- 適用於 JDK 24 的 GraalVM (搶先體驗版)
- 適用於 JDK 21 的 GraalVM
- 適用於 JDK 17 的 GraalVM
- 封存
- 開發建置版
- Truffle 語言實作框架
- Truffle 分支檢測
- 動態物件模型
- 靜態物件模型
- 直譯器程式碼的主機最佳化
- Truffle 函式內聯方法
- 剖析 Truffle 直譯器
- Truffle Interop 2.0
- 語言實作
- 使用 Truffle 實作新語言
- Truffle 語言和工具遷移至 Java 模組
- Truffle 原生函式介面
- 最佳化 Truffle 直譯器
- 選項
- 堆疊上替換
- Truffle 字串指南
- 特化直方圖
- 測試 DSL 特化
- 基於 Polyglot API 的 TCK
- Truffle 編譯佇列方法
- Truffle 程式庫指南
- Truffle AOT 總覽
- Truffle AOT 編譯
- 輔助引擎快取
- Truffle 語言安全點教學課程
- 單態化
- 分割演算法
- 單態化使用案例
- 向執行階段報告多型特化
Truffle 字串指南
Truffle 字串是 Truffle 的原始字串類型,可在語言之間共用。為了更容易互通和獲得更好的效能,建議語言實作者使用 Truffle 字串作為其語言的字串類型。
TruffleString
支援多種字串編碼,但特別針對最常用的編碼進行了最佳化
UTF-8
UTF-16
UTF-32
US-ASCII
ISO-8859-1
位元組
TruffleString API #
TruffleString
公開的所有操作都以內部 Node
的形式提供,並且作為靜態方法或實例方法提供。使用者應盡可能使用提供的節點,因為靜態/實例方法只是執行各自節點的未快取版本的簡寫。所有節點都命名為 {NameOfOperation}Node
,所有便捷方法都命名為 {nameOfOperation}Uncached
。
某些操作支援延遲求值,例如延遲串聯或某些字串屬性的延遲求值。這些操作大多提供一個參數 boolean lazy
,允許使用者在每次呼叫的基礎上啟用或停用延遲求值。
處理索引值的操作(例如 CodePointAtIndex
)有兩種變體:基於程式碼點的索引和基於位元組的索引。基於位元組的索引以操作名稱中的 ByteIndex
後綴或前綴表示,否則索引基於程式碼點。例如,CodePointAtIndex
的索引參數是基於程式碼點的,而 CodePointAtByteIndex
使用基於位元組的索引。
以下列出目前可用的操作,並按類別分組。
建立新的 TruffleString
- FromCodePoint:從給定的程式碼點建立新的 TruffleString。
- FromLong:從給定的 long 值建立新的 TruffleString。
- FromByteArray:從給定的位元組陣列建立新的 TruffleString。
- FromCharArrayUTF16:從給定的 char 陣列建立 UTF-16 TruffleString。
- FromIntArrayUTF32:從給定的 int 陣列建立 UTF-32 TruffleString。
- FromJavaString:從給定的
java.lang.String
建立 TruffleString。 - FromNativePointer:從給定的原生指標建立新的 TruffleString。
- Encoding#getEmpty:取得該編碼的空 TruffleString。
查詢字串屬性
- isEmpty:檢查字串是否為空。
- CodePointLength:取得字串的程式碼點長度。
- byteLength:取得字串的位元組長度。
- IsValid:檢查字串的編碼是否正確。
- GetCodeRange:取得字串內容的粗略資訊 (此字串中的所有程式碼點是否都來自 ASCII/LATIN-1/BMP 範圍?)。
- GetByteCodeRange:取得字串內容的粗略資訊,而不考慮基於 16/32 位元的編碼。
- CodeRangeEquals:檢查字串的程式碼範圍是否等於給定的程式碼範圍。
- isCompatibleTo:檢查字串是否與給定的編碼相容/是否可以以給定的編碼檢視。
- isManaged:檢查字串是否未由原生指標支援。
- isNative:檢查字串是否由原生指標支援。
- isImmutable:檢查字串是否為
TruffleString
的實例。 - isMutable:檢查字串是否為
MutableTruffleString
的實例。
比較
- Equal:檢查兩個字串是否相等。請注意,此操作對編碼敏感!
- RegionEqual:檢查兩個字串在由基於程式碼點的偏移量和長度定義的給定區域中是否相等。
- RegionEqualByteIndex:檢查兩個字串在由基於位元組的偏移量和長度定義的給定區域中是否相等。
- CompareBytes:逐位元組比較兩個字串。
- CompareCharsUTF16:逐字元比較兩個 UTF-16 字串。
- CompareIntsUTF32:逐 int 比較兩個 UTF-32 字串。
- HashCode:取得字串的雜湊碼。雜湊碼基於字串的位元組,因此具有相同程式碼點但編碼不同的字串可能具有不同的雜湊碼。
轉換
- SwitchEncoding:將字串轉換為給定的編碼。
- ForceEncoding:建立一個包含與給定字串相同位元組的字串,但分配給給定的編碼。
- AsTruffleString:將 MutableTruffleString 轉換為不可變的 TruffleString。
- AsManaged:將由原生指標支援的 TruffleString 轉換為由 java 位元組陣列支援的 TruffleString。
- ToValidString:將 TruffleString 轉換為正確編碼的版本。
- CopyToByteArray:將字串的內容複製到位元組陣列中。
- GetInternalByteArray:取得字串的內部位元組陣列。
- CopyToNativeMemory:將字串的內容複製到原生指標中。
- GetInternalNativePointer:取得原生字串的指標物件。
- ToJavaString:將字串轉換為
java.lang.String
。 - ParseInt:將字串的內容剖析為 int 值。
- ParseLong:將字串的內容剖析為 long 值。
- ParseDouble:將字串的內容剖析為 double 值。
存取程式碼點和位元組
- Materialize:使用此節點來避免在迴圈內迭代字串的程式碼點或位元組時進行實體化程式碼。
- ReadByte:從字串讀取單個位元組。
- ReadCharUTF16:從 UTF-16 字串讀取單個 char。
- CodePointAtIndex:從字串中讀取在給定基於程式碼點的索引處的單個程式碼點。
- CodePointAtByteIndex:從字串中讀取在給定基於位元組的索引處的單個程式碼點。
- CreateCodePointIterator: 傳回一個
TruffleStringIterator
物件,適用於迭代字串的碼位 (codepoint)。 - CreateBackwardCodePointIterator: 傳回一個
TruffleStringIterator
物件,適用於從字串的結尾開始迭代字串的碼位。 - ByteLengthOfCodePoint: 傳回從給定位元組索引開始的碼位所佔用的位元組數。
- CodePointIndexToByteIndex: 將給定的碼位索引轉換為給定字串上的位元組索引。
- ByteIndexToCodePointIndex: 將給定的位元組索引轉換為給定字串上的碼位索引。
搜尋
- ByteIndexOfAnyByte: 尋找字串中任何一組給定位元組的首次出現位置,並傳回其基於位元組的索引。
- CharIndexOfAnyCharUTF16: 尋找 UTF-16 字串中任何一組給定字元的首次出現位置,並傳回其基於字元的索引。
- IntIndexOfAnyIntUTF32: 尋找 UTF-32 字串中任何一組給定整數的首次出現位置,並傳回其基於整數的索引。
- IndexOfCodePoint: 尋找字串中給定碼位的首次出現位置,並傳回其基於碼位的索引。
- ByteIndexOfCodePoint: 尋找字串中給定碼位的首次出現位置,並傳回其基於位元組的索引。
- ByteIndexOfCodePointSet: 尋找字串中包含在給定集合中的碼位的首次出現位置,並傳回其基於位元組的索引。
- LastIndexOfCodePoint: 尋找字串中給定碼位的最後一次出現位置,並傳回其基於碼位的索引。
- LastByteIndexOfCodePoint: 尋找字串中給定碼位的最後一次出現位置,並傳回其基於位元組的索引。
- IndexOfString: 尋找字串中給定子字串的首次出現位置,並傳回其基於碼位的索引。
- ByteIndexOfString: 尋找字串中給定子字串的首次出現位置,並傳回其基於位元組的索引。
- LastIndexOfString: 尋找字串中給定子字串的最後一次出現位置,並傳回其基於碼位的索引。
- LastByteIndexOfString: 尋找字串中給定子字串的最後一次出現位置,並傳回其基於位元組的索引。
合併
- Concat: 連接兩個字串。
- Substring: 從給定字串建立子字串,以基於碼位的偏移量和長度為界。
- SubstringByteIndex: 從給定字串建立子字串,以基於位元組的偏移量和長度為界。
- Repeat: 將給定字串重複 n 次。
實例化 #
TruffleString
可以從碼位、數字、基本陣列或 java.lang.String
建立。
可以使用 TruffleString.FromByteArrayNode
建立任何編碼的字串,該節點預期一個包含已編碼字串的位元組陣列。透過將 copy
參數設定為 false
,此操作可以是非複製的。
重要事項:TruffleString
會假設陣列內容是不可變的,在將其傳遞給此操作的非複製變體後,請勿修改陣列。
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.strings.TruffleString;
abstract static class SomeNode extends Node {
@Specialization
static TruffleString someSpecialization(
@Cached TruffleString.FromByteArrayNode fromByteArrayNode) {
byte[] array = {'a', 'b', 'c'};
return fromByteArrayNode.execute(array, 0, array.length, TruffleString.Encoding.UTF_8, false);
}
}
為了更輕鬆地建立獨立於系統位元組順序的 UTF-16 和 UTF-32 字串,TruffleString
提供了 TruffleString.FromCharArrayUTF16Node
和 TruffleString.FromIntArrayUTF32Node
。
TruffleString
也可以透過 TruffleStringBuilder
建立,它是 TruffleString
對應於 java.lang.StringBuilder
的版本。
TruffleStringBuilder
提供以下操作
- AppendByte: 將單一位元組附加到字串建構器。
- AppendCharUTF16: 將單一字元附加到 UTF-16 字串建構器。
- AppendCodePoint: 將單一碼位附加到字串建構器。
- AppendIntNumber: 將整數數字附加到字串建構器。
- AppendLongNumber: 將長整數數字附加到字串建構器。
- AppendString: 將 TruffleString 附加到字串建構器。
- AppendSubstringByteIndex: 將子字串(由基於位元組的偏移量和長度定義)附加到字串建構器。
- AppendJavaStringUTF16: 將 Java 字串子字串(由基於字元的偏移量和長度定義)附加到字串建構器。
- ToString: 從字串建構器建立新的 TruffleString。
請參閱以下範例
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.api.strings.TruffleStringBuilder;
abstract static class SomeNode extends Node {
@Specialization
static TruffleString someSpecialization(
@Cached TruffleStringBuilder.AppendCharUTF16Node appendCharNode,
@Cached TruffleStringBuilder.AppendJavaStringUTF16Node appendJavaStringNode,
@Cached TruffleStringBuilder.AppendIntNumberNode appendIntNumberNode,
@Cached TruffleStringBuilder.AppendStringNode appendStringNode,
@Cached TruffleString.FromCharArrayUTF16Node fromCharArrayUTF16Node,
@Cached TruffleStringBuilder.AppendCodePointNode appendCodePointNode,
@Cached TruffleStringBuilder.ToStringNode toStringNode) {
TruffleStringBuilder sb = TruffleStringBuilder.create(TruffleString.Encoding.UTF_16);
sb = appendCharNode.execute(sb, 'a');
sb = appendJavaStringNode.execute(sb, "abc", /* fromIndex: */ 1, /* length: */ 2);
sb = appendIntNumberNode.execute(sb, 123);
TruffleString string = fromCharArrayUTF16Node.execute(new char[]{'x', 'y'}, /* fromIndex: */ 0, /* length: */ 2);
sb = appendStringNode.execute(sb, string);
sb = appendCodePointNode.execute(sb, 'z');
return toStringNode.execute(sb); // string content: "abc123xyz"
}
}
編碼 #
每個 TruffleString
都以特定的內部編碼進行編碼,該編碼在實例化期間設定。
TruffleString
針對以下編碼進行了完全最佳化
UTF-8
UTF-16
UTF-32
US-ASCII
ISO-8859-1
位元組
支援許多其他編碼,但未完全最佳化。若要使用它們,必須在 Truffle 語言註冊中設定 needsAllEncodings = true
來啟用它們。
TruffleString
的內部編碼不會公開。語言不應查詢字串的編碼,而應將 expectedEncoding
參數傳遞給字串編碼很重要的所有方法(幾乎所有操作)。如果字串在兩種編碼中是位元組等效的,這允許在編碼之間轉換時重複使用字串物件。可以使用 SwitchEncodingNode
將字串轉換為不同的編碼,如下列範例所示
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.api.strings.TruffleStringBuilder;
abstract static class SomeNode extends Node {
@Specialization
static void someSpecialization(
@Cached TruffleString.FromJavaStringNode fromJavaStringNode,
@Cached TruffleString.ReadByteNode readByteNode,
@Cached TruffleString.SwitchEncodingNode switchEncodingNode,
@Cached TruffleString.ReadByteNode utf8ReadByteNode) {
// instantiate a new UTF-16 string
TruffleString utf16String = fromJavaStringNode.execute("foo", TruffleString.Encoding.UTF_16);
// read a byte with expectedEncoding = UTF-16.
// if the string is not byte-compatible with UTF-16, this method will throw an IllegalArgumentException
System.out.printf("%x%n", readByteNode.execute(utf16String, /* byteIndex */ 0, TruffleString.Encoding.UTF_16));
// convert to UTF-8.
// note that utf8String may be reference-equal to utf16String!
TruffleString utf8String = switchEncodingNode.execute(utf16String, TruffleString.Encoding.UTF_8);
// read a byte with expectedEncoding = UTF-8
// if the string is not byte-compatible with UTF-8, this method will throw an IllegalArgumentException
System.out.printf("%x%n", utf8ReadByteNode.execute(utf8String, /* byteIndex */ 0, TruffleString.Encoding.UTF_8));
}
}
編碼之間的位元組等效性是透過 UTF-16 和 UTF-32 上的字串壓縮來確定的,因此,例如,壓縮的 UTF-16 字串在位元組上等效於 ISO-8859-1,並且如果其所有字元都在 ASCII 範圍內(請參閱 CodeRange
),則在位元組上也等效於 UTF-8。
若要檢查您的程式碼是否正確切換編碼,請使用系統屬性 truffle.strings.debug-strict-encoding-checks=true
執行您的單元測試。這會在切換編碼時停用重複使用字串物件,並使編碼檢查更加嚴格:所有在單一字串上運作的操作都會強制執行完全比對,而在兩個字串上運作的操作仍允許位元組等效的重新解譯。
所有具有多個字串參數的 TruffleString
操作都要求字串的編碼與結果編碼相容。因此,字串需要具有相同的編碼,或者呼叫端必須確保兩個字串都與結果編碼相容。這使已經知道 SwitchEncodingNodes
不會執行任何操作的呼叫端可以直接跳過它們,以減少資源佔用。
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.api.strings.TruffleStringBuilder;
abstract static class SomeNode extends Node {
@Specialization
static boolean someSpecialization(
TruffleString a,
TruffleString b,
@Cached TruffleString.SwitchEncodingNode switchEncodingNodeA,
@Cached TruffleString.SwitchEncodingNode switchEncodingNodeB,
@Cached TruffleString.EqualNode equalNode) {
TruffleString utf8A = switchEncodingNodeA.execute(a, TruffleString.Encoding.UTF_8);
TruffleString utf8B = switchEncodingNodeB.execute(b, TruffleString.Encoding.UTF_8);
return equalNode.execute(utf8A, utf8B, TruffleString.Encoding.UTF_8);
}
}
字串屬性 #
TruffleString
公開以下屬性
byteLength
:字串的位元組長度,透過byteLength
方法公開。codePointLength
:字串的碼位長度,透過CodePointLengthNode
公開。isValid
:可以使用IsValidNode
查詢,以檢查字串是否已正確編碼。codeRange
:提供有關字串內容的粗略資訊,透過GetCodeRangeNode
公開。此屬性可以具有以下值ASCII
:此字串中的所有碼位都是基本拉丁 Unicode 區塊(也稱為 ASCII)的一部分 (0x00 - 0x7f)。LATIN-1
:此字串中的所有碼位都是 ISO-8859-1 字元集 (0x00 - 0xff) 的一部分,該字元集等效於基本拉丁和拉丁-1 補充 Unicode 區塊的聯集。字串中至少有一個碼位大於 0x7f。僅適用於 ISO-8859-1、UTF-16 和 UTF-32。BMP
:此字串中的所有碼位都是 Unicode 基本多文種平面 (BMP) (0x0000 - 0xffff) 的一部分。字串中至少有一個碼位大於 0xff。僅適用於 UTF-16 和 UTF-32。VALID
:此字串已正確編碼,且包含至少一個超出其他適用碼位範圍的碼位(例如,對於 UTF-8,這表示有一個碼位超出 ASCII 範圍,對於 UTF-16,這表示有一個碼位超出 BMP 範圍)。BROKEN
:此字串未正確編碼。無法確定有關其內容的任何其他資訊。
hashCode
:字串的雜湊碼,透過HashCodeNode
公開。雜湊碼取決於字串的編碼;在比較雜湊碼之前,必須始終將字串轉換為通用編碼!
請參閱以下範例,了解如何查詢 TruffleString
公開的所有屬性
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.strings.TruffleString;
abstract static class SomeNode extends Node {
@Specialization
static TruffleString someSpecialization(
TruffleString string,
@Cached TruffleString.CodePointLengthNode codePointLengthNode,
@Cached TruffleString.IsValidNode isValidNode,
@Cached TruffleString.GetCodeRangeNode getCodeRangeNode,
@Cached TruffleString.HashCodeNode hashCodeNode) {
System.out.println("byte length: " + string.byteLength(TruffleString.Encoding.UTF_8));
System.out.println("codepoint length: " + codePointLengthNode.execute(string, TruffleString.Encoding.UTF_8));
System.out.println("is valid: " + isValidNode.execute(string));
System.out.println("code range: " + getCodeRangeNode.execute(string));
System.out.println("hash code: " + hashCodeNode.execute(string, TruffleString.Encoding.UTF_8));
}
}
字串相等性和比較 #
應使用 EqualNode
檢查 TruffleString
物件是否相等。就像 HashCodeNode
一樣,相等性比較對字串的編碼很敏感,因此在任何比較之前,應始終將字串轉換為通用編碼。Object#equals(Object)
的行為類似於 EqualNode
,但由於此方法沒有 expectedEncoding
參數,它將自動確定字串的通用編碼。如果字串的編碼不相等,TruffleString
將檢查一個字串的二進位是否與另一個字串的編碼相容,如果是,則比對它們的內容。否則,將認為字串不相等,不會套用自動轉換。
請注意,由於 TruffleString
的 hashCode
和 equals
方法對字串編碼很敏感,因此在例如將它們用作 HashMap
中的鍵之前,必須始終將 TruffleString
物件轉換為通用編碼。
TruffleString
還提供三個比較節點 CompareBytesNode
、CompareCharsUTF16Node
和 CompareIntsUTF32Node
,分別逐位元組、逐字元和逐整數比較字串。
串連 #
串連是透過 ConcatNode
完成的。此操作要求兩個字串都使用 expectedEncoding
,這也是結果字串的編碼。透過 lazy
參數支援延遲串連。當以延遲方式串連兩個字串時,會延遲新字串內部陣列的配置和初始化,直到另一個操作需要直接存取該陣列。可以使用 MaterializeNode
明確觸發此類「延遲串連字串」的實體化。在迴圈中存取字串之前執行此操作很有用,例如在以下範例中
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.strings.TruffleString;
abstract static class SomeNode extends Node {
@Specialization
static TruffleString someSpecialization(
TruffleString utf8StringA,
TruffleString utf8StringB,
@Cached TruffleString.ConcatNode concatNode,
@Cached TruffleString.MaterializeNode materializeNode,
@Cached TruffleString.ReadByteNode readByteNode) {
// lazy concatenation
TruffleString lazyConcatenated = concatNode.execute(utf8StringA, utf8StringB, TruffleString.Encoding.UTF_8, /* lazy */ true);
// explicit materialization
TruffleString materialized = materializeNode.execute(lazyConcatenated, TruffleString.Encoding.UTF_8);
int byteLength = materialized.byteLength(TruffleString.Encoding.UTF_8);
for (int i = 0; i < byteLength; i++) {
// string is guaranteed to be materialized here, so no slow materialization code can end up in this loop
System.out.printf("%x%n", readByteNode.execute(materialized, i, TruffleString.Encoding.UTF_8));
}
}
}
子字串 #
可以使用 SubstringNode
和 SubstringByteIndexNode
來建立子字串,它們分別使用基於碼位和基於位元組的索引。子字串也可以是 lazy
的,這表示不會為結果字串建立新的陣列,而是重複使用父字串的陣列,並且僅使用傳遞給子字串節點的偏移量和長度來存取。目前,lazy 子字串的內部陣列永遠不會被修剪(即,被字串精確長度的新陣列取代)。請注意,這種行為實際上會在建立 lazy 子字串時產生記憶體洩漏。一個極端的例子是,假設有一個 100 MB 大小的字串,從這個字串建立的任何 lazy 子字串都會保持這個 100 MB 的陣列處於活動狀態,即使原始字串被垃圾回收器釋放。使用 lazy 子字串時請務必謹慎。
與 java.lang.String
的互通性 #
TruffleString 提供了 FromJavaStringNode
用於將 java.lang.String
轉換為 TruffleString
。若要從 TruffleString
轉換為 java.lang.String
,請使用 ToJavaStringNode
。如有必要,此節點會在內部將字串轉換為 UTF-16,並從該表示法建立一個 java.lang.String
。
Object#toString()
是使用未快取的 ToJavaStringNode
版本實作的,應避免在快速路徑上使用。
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.strings.TruffleString;
abstract static class SomeNode extends Node {
@Specialization
static void someSpecialization(
@Cached TruffleString.FromJavaStringNode fromJavaStringNode,
@Cached TruffleString.SwitchEncodingNode switchEncodingNode,
@Cached TruffleString.ToJavaStringNode toJavaStringNode,
@Cached TruffleString.ReadByteNode readByteNode) {
TruffleString utf16String = fromJavaStringNode.execute("foo", TruffleString.Encoding.UTF_16);
TruffleString utf8String = switchEncodingNode.execute(utf16String, TruffleString.Encoding.UTF_8);
System.out.println(toJavaStringNode.execute(utf8String));
}
}
TruffleString
也公開了 #toStringDebug()
以用於除錯目的。請勿將此方法用於除錯以外的任何用途,因為其傳回值未指定,且可能隨時變更。
與 java.lang.String
的差異 #
從 java.lang.String
切換到 TruffleString
時,應考慮以下項目
TruffleString
實例的靜態額外負荷大於java.lang.String
物件的額外負荷。一個TruffleString
物件包含 2 個指標欄位、4 個int
欄位和 4 個byte
欄位,這通常會導致總物件大小為 40 個位元組(物件標頭為 12 個位元組,每個指標 4 個位元組(壓縮 oops),8 位元組的記憶體對齊)。一個java.lang.String
物件包含一個指標欄位、一個int
欄位和一個byte
欄位,在相同條件下,總物件大小為 24 個位元組。這種記憶體佔用空間的差異可能會對產生大量小字串的某些情況產生負面影響。TruffleString
與java.lang.String
一樣會進行字串壓縮。- 如果您的語言需要將字串轉換為其他編碼,例如 UTF-8(這在 Web 應用程式中非常常見),如果字串不包含特殊字元,
TruffleString
可以將此操作變成空操作。例如,僅限 ASCII 的字串可以重新解釋為幾乎任何編碼,並且將僅限 ASCII 的 UTF-16 字串轉換為 UTF-8 是空操作。在不可避免地需要轉碼字串的情況下,TruffleString
會將轉碼後的字串快取在原始字串中,因此每個字串和編碼只會執行一次轉碼。 - 為了使用第三方程式庫,必須將
TruffleString
物件轉換為java.lang.String
,然後再轉換回來。為了盡可能降低成本,當從java.lang.String
轉換為TruffleString
時,TruffleString
會重複使用 Java String 的內部位元組陣列,並且會將從TruffleString
物件建立的 Java String 快取在物件本身中。 TruffleString
提供了java.lang.String
中沒有的其他功能- Lazy 連接和字串檢視,可以顯著減少您的語言可能必須執行的陣列複製操作數量。
- 進入原生記憶體的
String
檢視,完全避免了在使用原生記憶體之前將其複製到 Java 陣列的需求。 - 透過
codeRange
屬性進行的String
內容分類,允許對僅限 ASCII 等字串進行特殊化。這可以顯著降低某些字串操作的複雜性。
- 所有
TruffleString
操作的效能應與其java.lang.String
對應項相同或更好。
碼位迭代器 #
TruffleString
提供了 TruffleStringIterator
作為迭代字串碼位的一種方式。此方法應優先於在迴圈中使用 CodePointAtIndexNode
,尤其是在可變寬度編碼(如 UTF-8)上,因為 CodePointAtIndexNode
可能必須在每次呼叫時重新計算給定碼位索引的等效位元組索引。
請參閱範例
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.api.strings.TruffleStringIterator;
abstract static class SomeNode extends Node {
@Specialization
static void someSpecialization(
TruffleString string,
@Cached TruffleString.CreateCodePointIteratorNode createCodePointIteratorNode,
@Cached TruffleStringIterator.NextNode nextNode,
@Cached TruffleString.CodePointLengthNode codePointLengthNode,
@Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
// iterating over a string's codepoints using TruffleStringIterator
TruffleStringIterator iterator = createCodePointIteratorNode.execute(string, TruffleString.Encoding.UTF_8);
while (iterator.hasNext()) {
System.out.printf("%x%n", nextNode.execute(iterator));
}
// suboptimal variant: using CodePointAtIndexNode in a loop
int codePointLength = codePointLengthNode.execute(string, TruffleString.Encoding.UTF_8);
for (int i = 0; i < codePointLength; i++) {
// performance problem: codePointAtIndexNode may have to calculate the byte index corresponding
// to codepoint index i for every loop iteration
System.out.printf("%x%n", codePointAtIndexNode.execute(string, i, TruffleString.Encoding.UTF_8));
}
}
}
可變字串 #
TruffleString
也提供了一個名為 MutableTruffleString
的可變字串變體,該變體也被 TruffleString
的所有節點接受。MutableTruffleString
是非執行緒安全的,並允許透過 WriteByteNode
覆寫其內部位元組陣列或原生指標中的位元組。內部陣列或原生指標的內容也可以在外部修改,但必須透過 notifyExternalMutation()
通知相應的 MutableTruffleString
。MutableTruffleString
不是 Truffle 互通類型,必須在傳遞語言邊界之前透過 TruffleString.AsTruffleString
轉換為不可變的 TruffleString
。