diff --git a/README-zh.md b/README-zh.md index 8abe385a..d289f0e3 100644 --- a/README-zh.md +++ b/README-zh.md @@ -378,11 +378,20 @@ byte[] bytes = FastProto.toBytes() * openjdk 1.8.0_292 * 二进制数据固定大小60字节,数据对象共包含13个不同类型的字段 +1. 注解式API + |Benchmark | 模式 | 样本数量 | 评分 | 误差 | 单位 | |:--------:|:--------:|:--------:|:--:|:---------:|:---------:| | `FastProto::parse` | 吞吐量 | 10 | 240 | ± 4.6 | 次/毫秒 | | `FastProto::toBytes` | 吞吐量 | 10 | 317 | ± 11.9 | 次/毫秒 | +2. 方法链式API + +|Benchmark | 模式 | 样本数量 | 评分 | 误差 | 单位 | +|:--------:|:--------:|:--------:|:--:|:---------:|:---------:| +| `FastProto::parse` | 吞吐量 | 10 | 1273 | ± 17 | 次/毫秒 | +| `FastProto::toBytes` | 吞吐量 | 10 | 6911 | ± 162 | 次/毫秒 | + ## *6. 构建要求* * Java 1.8+ diff --git a/benchmark/src/test/java/org/indunet/fastproto/benchmark/Sample.java b/benchmark/src/test/java/org/indunet/fastproto/benchmark/annotation/Sample.java similarity index 97% rename from benchmark/src/test/java/org/indunet/fastproto/benchmark/Sample.java rename to benchmark/src/test/java/org/indunet/fastproto/benchmark/annotation/Sample.java index fb9df8b0..694ab4b7 100644 --- a/benchmark/src/test/java/org/indunet/fastproto/benchmark/Sample.java +++ b/benchmark/src/test/java/org/indunet/fastproto/benchmark/annotation/Sample.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.indunet.fastproto.benchmark; +package org.indunet.fastproto.benchmark.annotation; import lombok.Data; import lombok.val; @@ -28,6 +28,8 @@ import static java.lang.Math.abs; /** + * Benchmark sample. + * * @author Deng Ran * @since 1.4.0 */ diff --git a/benchmark/src/test/java/org/indunet/fastproto/benchmark/FastProtoBenchmark.java b/benchmark/src/test/java/org/indunet/fastproto/benchmark/chain/FastProtoBenchmark.java similarity index 57% rename from benchmark/src/test/java/org/indunet/fastproto/benchmark/FastProtoBenchmark.java rename to benchmark/src/test/java/org/indunet/fastproto/benchmark/chain/FastProtoBenchmark.java index bb59f487..02356df4 100644 --- a/benchmark/src/test/java/org/indunet/fastproto/benchmark/FastProtoBenchmark.java +++ b/benchmark/src/test/java/org/indunet/fastproto/benchmark/chain/FastProtoBenchmark.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.indunet.fastproto.benchmark; +package org.indunet.fastproto.benchmark.chain; import lombok.val; import org.indunet.fastproto.FastProto; @@ -26,11 +26,13 @@ import java.util.concurrent.TimeUnit; +import static java.lang.Math.abs; + /** - * FastProto benchmark. + * FastProto benchmark of chain api. * * @author Deng Ran - * @since 1.4.0 + * @since 3.9.1 */ @State(Scope.Benchmark) public class FastProtoBenchmark { @@ -50,13 +52,37 @@ public static void main(String[] args) throws RunnerException { @Benchmark @OutputTimeUnit(TimeUnit.MILLISECONDS) public void parse() { - FastProto.parse(bytes, Sample.class); + FastProto.parse(bytes) + .readByte("byte8") + .readShort("short16") + .readInt32("int32") + .readInt64("long64") + .readFloat("float32") + .readDouble("double64") + .readInt8("int8") + .readInt16("int16") + .readUInt8("uint8") + .readUInt16("uint16") + .readUInt32("uint32") + .mapTo(Sample.class); } @Benchmark @OutputTimeUnit(TimeUnit.MILLISECONDS) public void toBytes() { - FastProto.toBytes(sample, this.bytes.length); + FastProto.toBytes(this.bytes.length) + .appendInt8(this.sample.byte8) + .appendInt16(this.sample.int16) + .appendInt32(this.sample.int32) + .appendInt64(this.sample.long64) + .appendFloat(this.sample.float32) + .appendDouble(this.sample.double64) + .appendInt8(this.sample.int8) + .appendInt16(this.sample.int16) + .appendUInt8(this.sample.uint8) + .appendUInt16(this.sample.uint16) + .appendUInt32(this.sample.uint32) + .get(); } @Setup diff --git a/benchmark/src/test/java/org/indunet/fastproto/benchmark/chain/Sample.java b/benchmark/src/test/java/org/indunet/fastproto/benchmark/chain/Sample.java new file mode 100644 index 00000000..cf63e22f --- /dev/null +++ b/benchmark/src/test/java/org/indunet/fastproto/benchmark/chain/Sample.java @@ -0,0 +1,94 @@ +/* + * Copyright 2019-2021 indunet.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.indunet.fastproto.benchmark.chain; + +import lombok.Data; +import lombok.val; +import org.indunet.fastproto.ByteOrder; +import org.indunet.fastproto.annotation.*; +import org.indunet.fastproto.util.CodecUtils; + +import java.util.Random; +import java.util.stream.IntStream; + +import static java.lang.Math.abs; + +/** + * Benchmark sample. + * + * @author Deng Ran + * @since 3.9.1 + */ +@Data +public class Sample { + Boolean bool1; + Byte byte8; + Short short16; + Integer int32; + Long long64; + Float float32; + Double double64; + Integer int8; + Integer int16; + Integer uint8; + Integer uint16; + Long uint32; + byte[] bytes; + + public Sample() { + val random = new Random(); + + this.bool1 = random.nextBoolean(); + this.byte8 = (byte) random.nextInt(Byte.MAX_VALUE); + this.short16 = (short) random.nextInt(Short.MAX_VALUE); + this.int32 = random.nextInt(); + this.long64 = random.nextLong(); + this.float32 = random.nextFloat(); + this.double64 = random.nextDouble(); + this.int8 = random.nextInt(Byte.MAX_VALUE); + this.int16 = random.nextInt(Short.MAX_VALUE); + this.uint8 = abs(random.nextInt(UInt8Type.MAX_VALUE)); + this.uint16 = abs(random.nextInt(UInt16Type.MAX_VALUE)); + this.uint32 = (long) abs(random.nextInt()); + + val bytes = new byte[10]; + + IntStream.range(0, bytes.length) + .forEach(i -> bytes[i] = (byte) random.nextInt(Byte.MAX_VALUE)); + this.bytes = bytes; + } + + public byte[] toBytes() { + val bytes = new byte[60]; + + CodecUtils.type(bytes, 0, 1, this.getBool1()); + CodecUtils.type(bytes, 1, this.getByte8()); + CodecUtils.type(bytes, 2, ByteOrder.LITTLE, this.getShort16()); + CodecUtils.type(bytes, 4, ByteOrder.LITTLE, this.getInt32()); + CodecUtils.type(bytes, 8, ByteOrder.LITTLE, this.getLong64()); + CodecUtils.type(bytes, 16, ByteOrder.LITTLE, this.getFloat32()); + CodecUtils.type(bytes, 20, ByteOrder.LITTLE, this.getDouble64()); + CodecUtils.int8Type(bytes, 28, this.getInt8()); + CodecUtils.int16Type(bytes, 30, ByteOrder.LITTLE, this.getInt16()); + CodecUtils.uint8Type(bytes, 32, this.getUint8()); + CodecUtils.uint16Type(bytes, 34, ByteOrder.LITTLE, this.getUint16()); + CodecUtils.uint32Type(bytes, 36, ByteOrder.LITTLE, this.getUint32()); + CodecUtils.type(bytes, 40, this.getBytes()); + + return bytes; + } +} diff --git a/src/main/java/org/indunet/fastproto/Decoder.java b/src/main/java/org/indunet/fastproto/Decoder.java index 4edf70e3..76ab1ef1 100644 --- a/src/main/java/org/indunet/fastproto/Decoder.java +++ b/src/main/java/org/indunet/fastproto/Decoder.java @@ -21,7 +21,7 @@ * @author Deng Ran * @since 3.8.3 */ -final class Decoder { +public final class Decoder { static ConcurrentHashMap constructorMap = new ConcurrentHashMap<>(); byte[] bytes; ByteBuffer byteBuffer; diff --git a/src/main/java/org/indunet/fastproto/Encoder.java b/src/main/java/org/indunet/fastproto/Encoder.java index dd9820a6..1aedc632 100644 --- a/src/main/java/org/indunet/fastproto/Encoder.java +++ b/src/main/java/org/indunet/fastproto/Encoder.java @@ -12,7 +12,7 @@ * @author Deng Ran * @since 3.8.3 */ -final class Encoder { +public final class Encoder { ByteBuffer byteBuffer; ByteOrder byteOrder = ByteOrder.LITTLE; BitOrder bitOrder = BitOrder.LSB_0; diff --git a/src/main/scala/org/indunet/fastproto/annotation/scala/package.scala b/src/main/scala/org/indunet/fastproto/annotation/scala/package.scala index 4381652a..df2cd04d 100644 --- a/src/main/scala/org/indunet/fastproto/annotation/scala/package.scala +++ b/src/main/scala/org/indunet/fastproto/annotation/scala/package.scala @@ -16,10 +16,14 @@ package org.indunet.fastproto.annotation -import org.indunet.fastproto.annotation.{BinaryType => JavaBinaryType, BoolType => JavaBoolType, CharType => JavaCharType, AsciiType => JavaAsciiType, DefaultByteOrder => JavaDefaultEndian, DoubleArrayType => JavaDoubleArrayType, DoubleType => JavaDoubleType, EnumType => JavaEnumType, FloatArrayType => JavaFloatArrayType, FloatType => JavaFloatType, Int16ArrayType => JavaInt16ArrayType, Int16Type => JavaInt16Type, Int32ArrayType => JavaInt32ArrayType, Int32Type => JavaInt32Type, Int64ArrayType => JavaInt64ArrayType, Int64Type => JavaInt64Type, Int8ArrayType => JavaInt8ArrayType, Int8Type => JavaInt8Type, StringType => JavaStringType, TimeType => JavaTimeType, UInt16ArrayType => JavaUInt16ArrayType, UInt16Type => JavaUInt16Type, UInt32ArrayType => JavaUInt32ArrayType, UInt32Type => JavaUInt32Type, UInt64ArrayType => JavaUInt64ArrayType, UInt64Type => JavaUInt64Type, UInt8ArrayType => JavaUInt8ArrayType, UInt8Type => JavaUInt8Type} +import org.indunet.fastproto.annotation.{BinaryType => JavaBinaryType, BoolType => JavaBoolType, CharType => JavaCharType, AsciiType => JavaAsciiType, DoubleArrayType => JavaDoubleArrayType, DoubleType => JavaDoubleType, EnumType => JavaEnumType, FloatArrayType => JavaFloatArrayType, FloatType => JavaFloatType, Int16ArrayType => JavaInt16ArrayType, Int16Type => JavaInt16Type, Int32ArrayType => JavaInt32ArrayType, Int32Type => JavaInt32Type, Int64ArrayType => JavaInt64ArrayType, Int64Type => JavaInt64Type, Int8ArrayType => JavaInt8ArrayType, Int8Type => JavaInt8Type, StringType => JavaStringType, TimeType => JavaTimeType, UInt16ArrayType => JavaUInt16ArrayType, UInt16Type => JavaUInt16Type, UInt32ArrayType => JavaUInt32ArrayType, UInt32Type => JavaUInt32Type, UInt64ArrayType => JavaUInt64ArrayType, UInt64Type => JavaUInt64Type, UInt8ArrayType => JavaUInt8ArrayType, UInt8Type => JavaUInt8Type} import org.indunet.fastproto.annotation.{AutoType => JavaAutoType} import org.indunet.fastproto.annotation.{EncodingIgnore => JavaEncodingIgnore} import org.indunet.fastproto.annotation.{DecodingIgnore => JavaDecodingIgnore} +import org.indunet.fastproto.annotation.{BoolArrayType => JavaBoolArrayType} +import org.indunet.fastproto.annotation.{CharArrayType => JavaCharArrayType} +import org.indunet.fastproto.annotation.{DefaultByteOrder => JavaDefaultByteOrder} +import org.indunet.fastproto.annotation.{DefaultBitOrder => JavaDefaultBitOrder} import org.indunet.fastproto.annotation.{FixedLength => JavaFixedLength} @@ -34,8 +38,10 @@ import _root_.scala.annotation.meta.field package object scala { type BinaryType = JavaBinaryType @field type BoolType = JavaBoolType @field + type BoolArrayType = JavaBoolArrayType @field type AsciiType = JavaAsciiType @field type CharType = JavaCharType @field + type CharArrayType = JavaCharArrayType @field type DoubleType = JavaDoubleType @field type DoubleArrayType = JavaDoubleArrayType @field type EnumType = JavaEnumType @field @@ -61,7 +67,8 @@ package object scala { type UInt64ArrayType = JavaUInt64ArrayType @field type AutoType = JavaAutoType @field - type DefaultEndian = JavaDefaultEndian @field + type DefaultByteOrder = JavaDefaultByteOrder @field + type DefaultBitOrder = JavaDefaultBitOrder @field type DecodingIgnore = JavaDecodingIgnore @field type EncodingIgnore = JavaEncodingIgnore @field