我从String
节点创建JSON
时遇到问题。
目前我正在通过node.toString()
方法进行此操作。但有时这需要7-8秒来创建加权15MB-18MB的JSON字符串。
我也尝试使用mapper.writeValueAsString(node))
方法。但它显示了一些额外的测试时间。这很难检查问题,因为它也很难重现。
我目前只使用ObjectNode
(不是TextNode
,BooleanNode
等)是否会对此产生影响?或者有没有更好的方法将JSONNode
转换为String
?
示例代码: JsonNodeFactory nodeFactory = JsonNodeFactory.instance;
ObjectNode node = nodeFactory.objectNode();
node.put("fnm", "Namal");
node.put("lnm", "Fernando");
node.put("age", 30);
for (int i = 0; i < 10000; i++) {
ObjectNode order = nodeFactory.objectNode();
order.put("id", (i+1000)+"");
order.put("nm", "ORD"+(i+1000));
order.put("ref", "RF-"+i);
node.put("order"+i, order);
}
long smili = System.currentTimeMillis();
System.out.println("main().Node : " + node.toString());
System.out.println("main().TIMING 1 : " + (System.currentTimeMillis() - smili) / 1000.0);;
long smili2 = System.currentTimeMillis();
ObjectMapper mapper = new ObjectMapper();
System.out.println("main().Node : " + mapper.writeValueAsString(node));
System.out.println("main().TIMING 2 : " + (System.currentTimeMillis() - smili2) / 1000.0);;
答案 0 :(得分:2)
首先要做的事情:JsonNode.toString()
不应该用于序列化。它对于简单的故障排除很有用,但由于它无法访问上下文配置,因此它不一定会生成有效的JSON。这是设计的。
相反,您应该使用ObjectMapper
或ObjectWriter
来序列化它;这将使用映射器具有的精确配置和设置(或映射器创建的编写器)生成有效的JSON。
现在:您的时间比较存在缺陷,因为您只使用ObjectMapper
进行一次通话。前N次呼叫有开销;部分原因是ObjectMapper
初始化,部分原因是JVM预热(动态JIT编译器运行优化等)。为了获得更多可用的结果,您需要多次调用方法,理想情况下让它运行几秒钟。
但除此之外,常见的问题是忘记拥有足够的堆空间。
在Java中,字符串要求内存至少相当于字符串长度的2倍(每个char
需要2个字节)。但这只是结果的大小;在序列化期间,还需要使用大致可比较的量的临时缓冲区。
但是,在磁盘上,UTF-8编码通常每个字符只使用1个字节(对于ASCII字符)。
因此,假设您看到一个15mB的文件,它可以在处理过程中使用60 MB的内存。如果您的堆大小设置为较小(例如,在许多情况下默认为64兆),则会导致非常繁重的垃圾收集处理。解决方案是增加堆大小。 或者,除非您确实需要String,否则:
String
或网络连接File
是反模式
byte[]
:这只需要与文件相同的内存量(因为它在内存中是UTF-8编码,而不是包裹{{1} }