优化反序列化的最佳方法是什么?
我目前正在使用标准的 Gson.toJson 和 Gson.fromJson 方法对一些复杂对象进行序列化和反序列化,并且我希望尽可能减少反序列化时间。
如果重要的话,我的对象中最复杂的包含 43 个变量。
如果你想使用 Gson,而不是切换到另一个 Java-to/from-JSON API,如果 Gson 的自动数据绑定性能不够好,那么可以继续使用 Gson API,并挤出一些性能较好。
在https://github.com/eishay/jvm-serializers/wiki上发布的最新几轮性能测试中,结果表明,通过使用流式传输,Gson 序列化和反序列化的综合性能可能会提高约 25% Gson 的 API,而不是数据绑定。
请注意,这通常会使用户代码的实现显着复杂化,其中类似于使用数据绑定 API 的单行代码的解决方案,例如,new Gson().toJson(something)
被(很容易)替换为数十行,包括循环和条件。因此,提高性能的代价是更复杂的代码。
有关使用流 API 与数据绑定 API 的示例,请查看jvm-serializers 项目JsonGsonManual
中的和JsonGsonDatabind
实现。
(注意:也可以在 Gson API 中使用树模型,而不是流式处理或数据绑定 API,但它似乎没有提供任何优于数据绑定的性能改进。有关示例,请参阅JsonGsonTree
。)
There is no way to improve the Gson library serialization and deserialization time.
As Programmer Bruce said, if the execution time really matters to you, take a look at the Jackson library. It is, in my opinion, a little bit more "complicated" to use but it has been proven much faster than any other json libraries in benchmarks.
Here are some best practices to improve performances with Jackson.
Gson 因其易用性而闻名和使用。如果你想要速度,你将不得不看看超级流行的 Jackson Json。
我已经对 Gson 和 Jackson 进行了测试和基准测试,我可以告诉你,在某些用例中,Jackson 在序列化和反序列化方面都快 15 倍,即使在非常大的对象上也是如此。
为了获得与 Json 类似的行为,我使用以下设置
public enum JsonMapper {
INSTANCE;
private final ObjectMapper mapper;
private JsonMapper() {
mapper = new ObjectMapper();
VisibilityChecker<?> visibilityChecker = mapper.getSerializationConfig().getDefaultVisibilityChecker();
mapper.setVisibilityChecker(visibilityChecker
.withFieldVisibility(Visibility.ANY)
.withCreatorVisibility(Visibility.NONE)
.withGetterVisibility(Visibility.NONE)
.withSetterVisibility(Visibility.NONE)
.withIsGetterVisibility(Visibility.NONE));
}
public ObjectMapper mapper() {
return mapper;
}
}
这将为相同的对象提供与 Gson 完全相同的 json 字符串。如果需要,您可以将其设置为仅使用 getter 和 setter。我建议您阅读有关处理子类型的所有杰克逊 json 注释(对 RPC 样式系统很有用)。
我的用例:当我需要将 blob 保存到存储系统(Redis、Cassandra、Mongo ......有时也是 mysql)时,我使用 jackson 作为序列化。我还将它用作我的 RPC 样式 API 的序列化,用于相当高流量的系统,尽管我更喜欢在可能的情况下使用 Protobuf。在最后一种情况下,我使用 Jackson 直接序列化为 byte[] 或流以获得更好的性能。
最后一点:对象映射器是线程安全的,并且像我刚刚提交的示例一样拥有一个静态实例将防止您产生轻微的实例化开销。
编辑:我知道我的示例没有遵循杰克逊页面中指出的许多最佳实践,但它使我可以轻松理解看起来像Gson.toJson
and的代码Gson.fromJson
(我也开始使用它,后来打开到杰克逊)
Gson.toJson(object)
=> JsonMapper.INSTANCE.mapper().writeValueAsString(object)
Gson.fromJson(object, clazz)
=>JsonMapper.INSTANCE.mapper().readValue(jsonString, clazz);
优化 json 最重要的事情是将所有数据保持在一个级别。
如果一个对象有另一个对象作为它的字段,而这个字段又是另一个对象等等,每new
一个都会消耗更多的时间来反序列化。如果对象的所有字段都具有原始类型,反序列化会更快一些。
Jackson 和 Gson 一直是帮助您的最佳图书馆。