Skip to content

Commit

Permalink
optimize readString
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Feb 12, 2025
1 parent 3151acc commit f6fd836
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 276 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void lambda(Blackhole bh) throws Throwable {
);
}

@Benchmark
// @Benchmark
public void direct(Blackhole bh) throws Throwable {
bh.consume(hasNegatives(bytes, 0, bytes.length));
}
Expand All @@ -76,11 +76,16 @@ public void isASCII(Blackhole bh) throws Throwable {
}

@Benchmark
public void isNonSlashASCII(Blackhole bh) throws Throwable {
bh.consume(com.alibaba.fastjson2.util.IOUtils.isNonSlashASCII(bytes, 0, bytes.length));
}

// @Benchmark
public void isLatin1(Blackhole bh) throws Throwable {
bh.consume(com.alibaba.fastjson2.util.IOUtils.isLatin1(chars, 0, chars.length));
}

@Benchmark
// @Benchmark
public void isASCIIJDK(Blackhole bh) throws Throwable {
bh.consume(com.alibaba.fastjson2.util.JDKUtils.PREDICATE_IS_ASCII.test(bytes));
}
Expand All @@ -90,17 +95,17 @@ public void indexOfSlash(Blackhole bh) throws Throwable {
bh.consume(com.alibaba.fastjson2.util.IOUtils.indexOfSlash(bytes, 0, bytes.length));
}

@Benchmark
// @Benchmark
public void indexOfSlashV(Blackhole bh) throws Throwable {
bh.consume(com.alibaba.fastjson2.util.IOUtils.indexOfSlashV(bytes, 0, bytes.length));
}

@Benchmark
// @Benchmark
public void indexOfChar(Blackhole bh) throws Throwable {
bh.consume(indexOfChar(bytes, '\'', 0, bytes.length));
}

@Benchmark
// @Benchmark
public void indexOfString(Blackhole bh) throws Throwable {
bh.consume(str.indexOf('\\'));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class EishayParseString {
}
}

@Benchmark
// @Benchmark
public void fastjson1(Blackhole bh) {
bh.consume(com.alibaba.fastjson.JSON.parseObject(str, MediaContent.class));
}
Expand All @@ -58,7 +58,7 @@ public void fastjson2Mixin(Blackhole bh) {
bh.consume(JSON.parseObject(str, MediaContent.class, JSONFactory.createReadContext(provider)));
}

@Benchmark
// @Benchmark
public void jackson(Blackhole bh) throws Exception {
bh.consume(mapper.readValue(str, MediaContent.class));
}
Expand All @@ -70,7 +70,7 @@ public void wastjson(Blackhole bh) throws Exception {
);
}

@Benchmark
// @Benchmark
public void gson(Blackhole bh) throws Exception {
bh.consume(
gson.fromJson(str, MediaContent.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class EishayParseUTF8Bytes {
}
}

@Benchmark
// @Benchmark
public void fastjson1(Blackhole bh) {
bh.consume(com.alibaba.fastjson.JSON.parseObject(utf8Bytes, MediaContent.class));
}
Expand Down
108 changes: 26 additions & 82 deletions core/src/main/java/com/alibaba/fastjson2/JSONReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -3252,33 +3252,20 @@ public static JSONReader of(byte[] utf8Bytes, Context context) {
}

public static JSONReader of(char[] chars) {
return new JSONReaderUTF16(
createReadContext(),
return ofUTF16(
null,
chars,
0,
chars.length);
chars.length, createReadContext());
}

@Deprecated
public static JSONReader of(Context context, char[] chars) {
return new JSONReaderUTF16(
context,
null,
chars,
0,
chars.length
);
return ofUTF16(null, chars, 0, chars.length, context);
}

public static JSONReader of(char[] chars, Context context) {
return new JSONReaderUTF16(
context,
null,
chars,
0,
chars.length
);
return ofUTF16(null, chars, 0, chars.length, context);
}

public static JSONReader ofJSONB(byte[] jsonbBytes) {
Expand Down Expand Up @@ -3344,11 +3331,11 @@ public static JSONReader of(byte[] bytes, int offset, int length, Charset charse
Context context = JSONFactory.createReadContext();

if (charset == StandardCharsets.UTF_8) {
return new JSONReaderUTF8(context, bytes, offset, length);
return JSONReaderUTF8.of(bytes, offset, length, context);
}

if (charset == StandardCharsets.UTF_16) {
return new JSONReaderUTF16(context, bytes, offset, length);
return ofUTF16(bytes, offset, length, context);
}

if (charset == StandardCharsets.US_ASCII || charset == StandardCharsets.ISO_8859_1) {
Expand All @@ -3358,13 +3345,23 @@ public static JSONReader of(byte[] bytes, int offset, int length, Charset charse
throw new JSONException("not support charset " + charset);
}

private static JSONReader ofUTF16(byte[] bytes, int offset, int length, Context ctx) {
return new JSONReaderUTF16(ctx, bytes, offset, length);
}

private static JSONReader ofUTF16(String str, char[] chars, int offset, int length, Context ctx) {
return (str != null && str.indexOf('\\') == -1) || IOUtils.isNonSlashASCII(chars, offset, length)
? new JSONReaderUTF16NonSlash(ctx, str, chars, offset, length)
: new JSONReaderUTF16(ctx, str, chars, offset, length);
}

public static JSONReader of(byte[] bytes, int offset, int length, Charset charset, Context context) {
if (charset == StandardCharsets.UTF_8) {
return JSONReaderUTF8.of(bytes, offset, length, context);
}

if (charset == StandardCharsets.UTF_16) {
return new JSONReaderUTF16(context, bytes, offset, length);
return ofUTF16(bytes, offset, length, context);
}

if (charset == StandardCharsets.US_ASCII || charset == StandardCharsets.ISO_8859_1) {
Expand All @@ -3383,11 +3380,11 @@ public static JSONReader of(byte[] bytes, int offset, int length, Context contex
}

public static JSONReader of(char[] chars, int offset, int length) {
return new JSONReaderUTF16(createReadContext(), null, chars, offset, length);
return ofUTF16(null, chars, offset, length, createReadContext());
}

public static JSONReader of(char[] chars, int offset, int length, Context context) {
return new JSONReaderUTF16(context, null, chars, offset, length);
return ofUTF16(null, chars, offset, length, context);
}

public static JSONReader of(URL url, Context context) throws IOException {
Expand Down Expand Up @@ -3415,9 +3412,7 @@ public static JSONReader of(InputStream is, Charset charset, Context context) {
}

if (charset == StandardCharsets.US_ASCII) {
return JVM_VERSION == 8
? new JSONReaderASCIIJDK8(context, is)
: new JSONReaderASCII(context, is);
return new JSONReaderASCII(context, is);
}

return JSONReader.of(new InputStreamReader(is, charset), context);
Expand Down Expand Up @@ -3461,33 +3456,7 @@ public static JSONReader of(Context context, String str) {
}

public static JSONReader of(String str) {
if (str == null) {
throw new NullPointerException();
}

Context context = JSONFactory.createReadContext();
if (STRING_VALUE != null && STRING_CODER != null) {
try {
final int LATIN1 = 0;
int coder = STRING_CODER.applyAsInt(str);
if (coder == LATIN1) {
byte[] bytes = STRING_VALUE.apply(str);
if (PREDICATE_IS_ASCII != null && PREDICATE_IS_ASCII.test(bytes)) {
return new JSONReaderASCII(context, str, bytes, 0, bytes.length);
}
}
} catch (Exception e) {
throw new JSONException("unsafe get String.coder error");
}
}

final int length = str.length();
if (JVM_VERSION == 8) {
char[] chars = JDKUtils.getCharArray(str);
return new JSONReaderUTF16(context, str, chars, 0, length);
}

return new JSONReaderUTF16(context, str, 0, length);
return of(str, JSONFactory.createReadContext());
}

public static JSONReader of(String str, Context context) {
Expand All @@ -3501,7 +3470,7 @@ public static JSONReader of(String str, Context context) {
int coder = STRING_CODER.applyAsInt(str);
if (coder == LATIN1) {
byte[] bytes = STRING_VALUE.apply(str);
return new JSONReaderASCII(context, str, bytes, 0, bytes.length);
return JSONReaderASCII.of(context, str, bytes, 0, bytes.length);
}
} catch (Exception e) {
throw new JSONException("unsafe get String.coder error");
Expand All @@ -3516,36 +3485,11 @@ public static JSONReader of(String str, Context context) {
chars = str.toCharArray();
}

return new JSONReaderUTF16(context, str, chars, 0, length);
return ofUTF16(str, chars, 0, length, context);
}

public static JSONReader of(String str, int offset, int length) {
if (str == null) {
throw new NullPointerException();
}

Context context = JSONFactory.createReadContext();
if (STRING_VALUE != null) {
try {
final int LATIN1 = 0;
int coder = STRING_CODER.applyAsInt(str);
if (coder == LATIN1) {
byte[] bytes = STRING_VALUE.apply(str);
return new JSONReaderASCII(context, str, bytes, offset, length);
}
} catch (Exception e) {
throw new JSONException("unsafe get String.coder error");
}
}

char[] chars;
if (JVM_VERSION == 8) {
chars = JDKUtils.getCharArray(str);
} else {
chars = str.toCharArray();
}

return new JSONReaderUTF16(context, str, chars, offset, length);
return of(str, offset, length, JSONFactory.createReadContext());
}

public static JSONReader of(String str, int offset, int length, Context context) {
Expand All @@ -3559,7 +3503,7 @@ public static JSONReader of(String str, int offset, int length, Context context)
int coder = STRING_CODER.applyAsInt(str);
if (coder == LATIN1) {
byte[] bytes = STRING_VALUE.apply(str);
return new JSONReaderASCII(context, str, bytes, offset, length);
return JSONReaderASCII.of(context, str, bytes, offset, length);
}
} catch (Exception e) {
throw new JSONException("unsafe get String.coder error");
Expand All @@ -3573,7 +3517,7 @@ public static JSONReader of(String str, int offset, int length, Context context)
chars = str.toCharArray();
}

return new JSONReaderUTF16(context, str, chars, offset, length);
return ofUTF16(str, chars, offset, length, context);
}

final void bigInt(char[] chars, int off, int len) {
Expand Down
45 changes: 26 additions & 19 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ public final long readValueHashCode() {

long nameValue = 0;
for (int i = 0; offset < end; offset++, i++) {
ch = bytes[offset];
ch = bytes[offset] & 0xff;

if (ch == quote) {
if (i == 0) {
Expand Down Expand Up @@ -1474,23 +1474,7 @@ public String readString() {
offset = readEscaped(bytes, start, quote, buf);
str = new String(buf);
} else {
if (this.str != null) {
str = this.str.substring(start, offset);
} else if (STRING_CREATOR_JDK11 != null) {
str = STRING_CREATOR_JDK11.apply(Arrays.copyOfRange(bytes, start, offset), LATIN1);
} else if (ANDROID) {
str = getLatin1String(start, offset - start);
} else {
str = new String(bytes, start, offset - start, StandardCharsets.ISO_8859_1);
}
}

if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
str = subString(bytes, start, offset);
}

int ch = ++offset == end ? EOI : bytes[offset++];
Expand Down Expand Up @@ -1560,7 +1544,30 @@ protected final int readEscaped(byte[] bytes, int offset, byte quote, char[] buf
return offset;
}

protected final String subString(byte[] bytes, int start, int offset) {
String str;
if (this.str != null) {
str = this.str.substring(start, offset);
} else if (STRING_CREATOR_JDK11 != null) {
str = STRING_CREATOR_JDK11.apply(Arrays.copyOfRange(bytes, start, offset), LATIN1);
} else if (ANDROID) {
str = getLatin1String(start, offset - start);
} else {
str = new String(bytes, start, offset - start, StandardCharsets.ISO_8859_1);
}
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}

public static JSONReaderASCII of(Context ctx, String str, byte[] bytes, int offset, int length) {
return new JSONReaderASCII(ctx, str, bytes, offset, length);
return IOUtils.isNonSlashASCII(bytes, offset, length)
? new JSONReaderASCIINonSlash(ctx, str, bytes, offset, length)
: new JSONReaderASCII(ctx, str, bytes, offset, length);
}
}
Loading

0 comments on commit f6fd836

Please sign in to comment.