在 Jackson 中将 4Mb JSON 转换为 java 对象需要 1500 毫秒

问题描述 投票:0回答:2

在我的应用程序中,一个实体建模如下:

class Node{
     private String parentNodeId;
     private Node parentNode;
     // other properties and their `getters` and setters
}

因为我对

NoSql
DB 使用非规范化形式。每个节点都有其父节点引用。这样在数据库中我就有了 540 条记录,大约有 4Mb 的
JSON
数据。从数据库获取这些记录不需要太多时间(70ms)。但是将那些从
JSON
反序列化为 Java 对象需要近 1500 毫秒。合并所有请求来完成它需要 2000 毫秒。进行转换的代码如下

List<String> records = DB.get("some criteria");
List<Node> results = Lists.newArrayList();
for(String entity : records){
   results.add(convertJSONToObject(entity, Node.class));
}

private <T> T convertJSONToObject(String record, Class<T> entityClass){
      if(StringUtils.isBlank(json)){
         return null;
      }
      ObjectReader reader = MAPPER.reader(objectClass);
      return reader.readValue(json);
}

有没有更好的方法可以减少转换时间,或者这个速度对于那么多数据来说是可以接受的?

java json performance jackson
2个回答
1
投票

由于将对象模型完全保存在内存中以及这些模型的复杂性(可能有很多 POJO),文档解析器可能相当重。

首先,值得对反序列化过程进行分析,以确保它不会受到 IO 限制、花费大量时间进行反射或发生某种线程争用。其中可能存在一些您可以轻松修复或优化的问题。

其次,现代系统上的性能可以通过多线程获得很大的提高。也许可以考虑将您的 JSON 模型分解为多个部分并并行反序列化它们,或者看看 Jackson 是否可以选择为您执行此操作。

如果您要定期需要这些对象并且您的数据有一定的生命周期,您可能需要考虑缓存这些对象并拥有一种在适当的时间使它们失效或更新的机制。您还应该考虑排除您不会使用的字段。

另一件需要注意的事情是您是否需要立即反序列化整个对象。我相信 Jackson 确实有能力提供随机访问,因此,当您等待 1500 毫秒进行反序列化时,您可以通过该方法提供临时访问并简单地反序列化所需的字段。或者,完全接受这种方法——为什么要反序列化你不需要的东西?

更进一步,如果您正在处理所有对象,您可能需要考虑使用流解析器。如果这是工作流程的一部分并且不排除在此过程中分叉对象模型,那么这将更适合。

如果您不确定杰克逊的表现,可能值得分析替代方案,看看它们是否做得更好。在某些条件下,GSON已被证明比Jackson快很多,还有JSONP和JSON.simple。针对您的用例进行基准测试将使您更好地了解其中哪些最适合您。


0
投票

如果可能的话,尝试用

String
以外的任何东西喂 Jackson,b/c 这是最不节省内存的方式。

例如,使用

byte[]
代替
String
会减少 50% 的内存消耗,因此所需的处理时间会大大减少,正如 Jackson 贡献者 StaxMan 在此处此处所解释的那样。

其他选项(取决于数据传入的方式)是直接向 Jackson 提供

URL
File
InputStream
,如 Jackson 性能最佳实践第 3 节中所建议。

© www.soinside.com 2019 - 2024. All rights reserved.