1:依赖
implementation "io.protostuff:protostuff-core:1.8.0"
implementation "io.protostuff:protostuff-runtime:1.8.0"
2:代码
package tech.tongyu.etrade.trsmanager.utils;
import cn.hutool.core.collection.CollUtil;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.runtime.RuntimeSchema;
import org.apache.commons.lang3.SerializationUtils;
import tech.tongyu.etrade.trsmanager.feign.DTO.PriceChangeRankingItemDTO;
import tech.tongyu.idp.model.SecurityExchange;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("unchecked")
public class ProtostuffUtils {
/** Schema 缓存 */
private static final Map<Class<?>, RuntimeSchema<?>> SCHEMA_CACHE = new ConcurrentHashMap<>();
/** 每个线程复用一个 buffer —— 性能最优 */
private static final ThreadLocal<LinkedBuffer> BUFFER_LOCAL = ThreadLocal.withInitial(() -> LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
/** 获取 schema(带缓存) */
private static <T> RuntimeSchema<T> getSchema(Class<T> clazz) {
return (RuntimeSchema<T>) SCHEMA_CACHE.computeIfAbsent(clazz, RuntimeSchema::createFrom);
}
/** Protostuff 单对象序列化 */
public static <T> byte[] serialize(T obj) {
if (obj == null) return new byte[0];
Class<T> clazz = (Class<T>) obj.getClass();
RuntimeSchema<T> schema = getSchema(clazz);
LinkedBuffer buffer = BUFFER_LOCAL.get();
try {
return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} finally {
buffer.clear();
}
}
/** Protostuff 单对象反序列化 */
public static <T> T deserialize(byte[] data, Class<T> clazz) {
if (data == null || data.length == 0) return null;
RuntimeSchema<T> schema = getSchema(clazz);
T obj = schema.newMessage();
ProtostuffIOUtil.mergeFrom(data, obj, schema);
return obj;
}
/** Protostuff list 列表序列化 */
public static <T> byte[] serializeList(List<T> list) {
if (CollUtil.isEmpty(list)) return new byte[0];
Class<T> clazz = (Class<T>) list.get(0).getClass();
RuntimeSchema<T> schema = getSchema(clazz);
LinkedBuffer buffer = BUFFER_LOCAL.get();
// 预估大小(减少扩容开销)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(Math.max(512, list.size() * 64));
try {
ProtostuffIOUtil.writeListTo(outputStream, list, schema, buffer);
return outputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Protostuff 列表序列化失败", e);
} finally {
buffer.clear();
}
}
/** Protostuff list 列表反序列化 */
public static <T> List<T> deserializeList(byte[] data, Class<T> clazz) {
if (data == null || data.length == 0) return Collections.emptyList();
RuntimeSchema<T> schema = getSchema(clazz);
try (ByteArrayInputStream bais = new ByteArrayInputStream(data)) {
return ProtostuffIOUtil.parseListFrom(bais, schema);
} catch (IOException e) {
throw new RuntimeException("Protostuff 列表反序列化失败", e);
}
}
}
3:测试 53000 条数据
public static void main(String[] args) {
List<PriceChangeRankingItemDTO> list = new ArrayList<>();
for (int i = 0; i < 53000; i++) {
PriceChangeRankingItemDTO itemDTO = new PriceChangeRankingItemDTO();
itemDTO.setSecurityId("000001.XSHE");
itemDTO.setSecurityExchange(SecurityExchange.SH);
itemDTO.setLatestPrice(new BigDecimal("10.0"));
itemDTO.setPriceChangePercentage(new BigDecimal("0.1"));
list.add(itemDTO);
}
// -------- 序列化耗时 --------
long t1 = System.nanoTime();
byte[] bytes = serializeList(list);
long t2 = System.nanoTime();
// -------- 反序列化耗时 --------
long t3 = System.nanoTime();
List<PriceChangeRankingItemDTO> list1 = deserializeList(bytes, PriceChangeRankingItemDTO.class);
long t4 = System.nanoTime();
long t5 = System.nanoTime();
byte[] serialize = SerializationUtils.serialize((Serializable) list);
long t6 = System.nanoTime();
long t7 = System.nanoTime();
Object deserialize = SerializationUtils.deserialize(serialize);
long t8 = System.nanoTime();
System.out.println("序列化耗时: " + (t2 - t1) / 1_000_000.0 + " ms");
System.out.println("反序列化耗时: " + (t4 - t3) / 1_000_000.0 + " ms");
System.out.println("SerializationUtils 序列化耗时: " + (t6 - t5) / 1_000_000.0 + " ms");
System.out.println("SerializationUtils 反序列化耗时: " + (t8 - t7) / 1_000_000.0 + " ms");
System.out.println("list1 size = " + list1.size());
4:测试截图
