Skip to content

Commit

Permalink
improved serialize BigInteger performance
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Aug 15, 2023
1 parent fd2b2fa commit 59c2622
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONB;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.benchmark.primitves.vo.BigInteger20Field;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
Expand Down Expand Up @@ -49,6 +50,12 @@ public void fastjson2(Blackhole bh) {
);
}

public void fastjson2_array_bytes(Blackhole bh) {
bh.consume(
JSON.toJSONBytes(bean, JSONWriter.Feature.BeanToArray)
);
}

@Benchmark
public void jsonb(Blackhole bh) {
bh.consume(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,24 @@ public static void fastjson2() {
benchmark.fastjson2(BH);
}
long millis = System.currentTimeMillis() - start;
System.out.println("BigDecimal20-fastjson2 : " + millis);
System.out.println("BigInteger20-fastjson2 : " + millis);

// zulu8.68.0.21 : 367
// zulu8.68.0.21 : 367 246
// zulu11.52.13 :
// zulu17.32.13 :
}
}

public static void fastjson2_array_bytes() {
for (int j = 0; j < 10; j++) {
long start = System.currentTimeMillis();
for (int i = 0; i < 1000 * 1000; ++i) {
benchmark.fastjson2_array_bytes(BH);
}
long millis = System.currentTimeMillis() - start;
System.out.println("BigInteger20-fastjson2_array_bytes : " + millis);

// zulu8.68.0.21 : 1166
// zulu11.52.13 :
// zulu17.32.13 :
}
Expand All @@ -27,9 +42,9 @@ public static void jsonb() {
benchmark.jsonb(BH);
}
long millis = System.currentTimeMillis() - start;
System.out.println("BigDecimal20-jsonb : " + millis);
System.out.println("BigInteger20-jsonb : " + millis);

// zulu8.62.0.19 :
// zulu8.62.0.19 : 280
// zulu11.52.13 :
// zulu17.40.19 :
}
Expand All @@ -42,8 +57,8 @@ public static void jackson() throws Exception {
benchmark.jackson(BH);
}
long millis = System.currentTimeMillis() - start;
System.out.println("BigDecimal20-jackson : " + millis);
// zulu8.62.0.19 :
System.out.println("BigInteger20-jackson : " + millis);
// zulu8.62.0.19 : 1150
// zulu11.52.13 :
// zulu17.32.13 :
}
Expand All @@ -56,20 +71,18 @@ public static void wastjson() throws Exception {
benchmark.wastjson(BH);
}
long millis = System.currentTimeMillis() - start;
System.out.println("BigDecimal20-wastjson : " + millis);
// zulu8.62.0.19 :
System.out.println("BigInteger20-wastjson : " + millis);
// zulu8.62.0.19 : 1104
// zulu11.52.13 :
// zulu17.32.13 :
}
}

public static void main(String[] args) throws Exception {
// fastjson2();
// fastjson2_array_bytes();
jsonb();
// hessian();
// fury();
// jackson();
// wastjson();
// kryo();
}
}
6 changes: 6 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
import static com.alibaba.fastjson2.util.IOUtils.*;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.TypeUtils.isInt64;

class JSONWriterUTF16
extends JSONWriter {
Expand Down Expand Up @@ -1233,6 +1234,11 @@ public final void writeBigInt(BigInteger value, long features) {
return;
}

if (isInt64(value) && features == 0) {
writeInt64(value.longValue());
return;
}

String str = value.toString(10);

features |= context.features;
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
import static com.alibaba.fastjson2.util.IOUtils.*;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.TypeUtils.isInt64;

class JSONWriterUTF8
extends JSONWriter {
Expand Down Expand Up @@ -2468,6 +2469,11 @@ public final void writeBigInt(BigInteger value, long features) {
return;
}

if (isInt64(value) && features == 0) {
writeInt64(value.longValue());
return;
}

String str = value.toString(10);

if (((context.features | features) & Feature.BrowserCompatible.mask) != 0
Expand Down
13 changes: 13 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteOrder;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -27,6 +28,7 @@ public class JDKUtils {
public static volatile boolean FIELD_STRING_VALUE_ERROR;

public static final long FIELD_DECIMAL_INT_COMPACT_OFFSET;
public static final long FIELD_BIGINTEGER_MAG_OFFSET;

public static final Field FIELD_STRING_CODER;
public static final long FIELD_STRING_CODER_OFFSET;
Expand Down Expand Up @@ -183,6 +185,17 @@ public class JDKUtils {
FIELD_DECIMAL_INT_COMPACT_OFFSET = fieldOffset;
}

{
long fieldOffset = -1;
try {
Field field = BigInteger.class.getDeclaredField("mag");
fieldOffset = UNSAFE.objectFieldOffset(field);
} catch (Throwable ignored) {
// ignored
}
FIELD_BIGINTEGER_MAG_OFFSET = fieldOffset;
}

BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;

BiFunction<char[], Boolean, String> stringCreatorJDK8 = null;
Expand Down
10 changes: 8 additions & 2 deletions core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.*;

import static com.alibaba.fastjson2.util.JDKUtils.FIELD_DECIMAL_INT_COMPACT_OFFSET;
import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.JDKUtils.FIELD_BIGINTEGER_MAG_OFFSET;
import static java.lang.invoke.MethodType.methodType;

public class TypeUtils {
Expand Down Expand Up @@ -1883,6 +1883,12 @@ public static boolean isInt32(BigInteger value) {
}

public static boolean isInt64(BigInteger value) {
if (FIELD_BIGINTEGER_MAG_OFFSET != -1) {
int[] mag = (int[]) UNSAFE.getObject(value, FIELD_BIGINTEGER_MAG_OFFSET);
if (mag.length == 1 || (mag.length == 2 && mag[0] >= 0)) {
return true;
}
}
return value.compareTo(BIGINT_INT64_MIN) >= 0 && value.compareTo(BIGINT_INT64_MAX) <= 0;
}

Expand Down

0 comments on commit 59c2622

Please sign in to comment.