/** * 与kryo对比,都是启用新线程,每隔1秒执行10000次,执行效率和序列化后的字节大小都是kryo完胜 * * @author zkpursuit */ public class ProtostuffSerializer<T> implements Serializer<T> { private static final Map<Long, Schema<?>> schemaCache = new ConcurrentHashMap<>(); private static <T> Schema<T> getSchema(Class<T> clazz, long clazzId) { Schema<T> schema = (Schema<T>) schemaCache.get(clazzId); if (Objects.isNull(schema)) { schema = RuntimeSchema.getSchema(clazz); if (Objects.nonNull(schema)) { schemaCache.put(clazzId, schema); } } return schema; } private static <T> Schema<T> getSchema(long typeId) { return (Schema<T>) schemaCache.get(typeId); } @Override public byte[] serialize(T obj) { Class<T> clazz = (Class<T>) obj.getClass(); String className = clazz.getTypeName(); long classId = StringUtils.toNumber(className); //将类的唯一限定名转换为唯一ID,实现原理是将字符串转为MD5后再转为long型数字,由于一个项目中类数量限制,MD5的重复命中可以忽略,由于算法本身缘故,会有一点性能损耗,有待优化。 Schema<T> schema = getSchema(clazz, classId); LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); //此处可优化为使用对象池 byte[] data = ProtostuffIOUtil.toByteArray(obj, schema, buffer); buffer.clear(); byte[] typeIdBytes = ByteUtils.getBytes(classId); byte[] bytes = new byte[8 + data.length]; //将类的唯一id写入序列化字节数组首部,固定占用8个字节 System.arraycopy(typeIdBytes, 0, bytes, 0, typeIdBytes.length); System.arraycopy(data, 0, bytes, typeIdBytes.length, data.length); return bytes; } @Override public T deserialize(byte[] bytes) { long id = ByteUtils.toLong(bytes, 0); //解析出首部8字节的唯一类名ID Schema<T> schema = getSchema(id); if (schema == null) return null; byte[] data = new byte[bytes.length - 8]; System.arraycopy(bytes, 8, data, 0, data.length); T obj = schema.newMessage(); ProtostuffIOUtil.mergeFrom(data, obj, schema); return obj; } }
Protostuff序列化与反序列化,反序列化时无须传入类
于 2022-03-05 18:01:36 首次发布
本文探讨了ProtostuffSerializer与Kryo在序列化性能上的对比,展示了在高并发场景下,ProtostuffSerializer在执行效率和序列化后的字节大小上不如Kryo。作者分享了代码实例并提出了MD5转换类ID的性能优化点。
摘要由CSDN通过智能技术生成