diff --git a/benchmark/src/main/java/com/alibaba/fastjson2/benchmark/primitves/BigInteger20.java b/benchmark/src/main/java/com/alibaba/fastjson2/benchmark/primitves/BigInteger20.java index b2444401d5..17c39dd61a 100644 --- a/benchmark/src/main/java/com/alibaba/fastjson2/benchmark/primitves/BigInteger20.java +++ b/benchmark/src/main/java/com/alibaba/fastjson2/benchmark/primitves/BigInteger20.java @@ -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; @@ -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( diff --git a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/primitves/BigInteger20Test.java b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/primitves/BigInteger20Test.java index 2157f006fc..e0f67d945e 100644 --- a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/primitves/BigInteger20Test.java +++ b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/primitves/BigInteger20Test.java @@ -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 : } @@ -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 : } @@ -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 : } @@ -56,8 +71,8 @@ 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 : } @@ -65,11 +80,9 @@ public static void wastjson() throws Exception { public static void main(String[] args) throws Exception { // fastjson2(); +// fastjson2_array_bytes(); jsonb(); -// hessian(); -// fury(); // jackson(); // wastjson(); -// kryo(); } } diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java index 5d76d52d2f..326192aa16 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java @@ -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 { @@ -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; diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java index efb0f028ab..e1c6440109 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java @@ -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 { @@ -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 diff --git a/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java index dce4add3d1..71518cf775 100644 --- a/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java +++ b/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java @@ -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; @@ -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; @@ -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 stringCreatorJDK8 = null; diff --git a/core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java index a50ed4574c..bc949357c1 100644 --- a/core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java +++ b/core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java @@ -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 { @@ -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; }