为什么Jackson如此缓慢?

5

我使用简单的Jackson代码将我的对象转换为JSON字符串,但速度非常慢。在我的机器上,仅将一个对象转换需要70毫秒,我做错了什么吗?

ObjectMapper myObjectMapper = new ObjectMapper();
void testJson()
{

    MyClass state = new MyClass();
    try
    {
        String result = myObjectMapper.writeValueAsString(state);
    } catch (Exception ex)
    {

    }

}

只有4个成员的MyClass

 MyClass
    {
    public int a;
        public  int b;
        public int c;
        public String d;
    }

6
你不能仅凭一次的结果来衡量性能... 尝试运行它1000次,你会发现它所需要的时间远远小于70毫秒 * 1000。 - fge
2
内置序列化和Jackson根本没有相同的目的!你在比较不同的东西。如果你想使用Jackson,那就意味着你需要使用JSON;内置序列化无法为你完成这个任务。 - fge
是的,你知道其他将对象转换为字节数组的方法吗?这就是我正在做的事情。 - daddylonglegs
你的问题不够清晰,你想用这个字节数组做什么?发送给同行?仅在本地使用? - fge
我将对象转换为字节数组以通过TCP网络发送。我需要同时具备高速和小尺寸。 - daddylonglegs
显示剩余6条评论
1个回答

10
我使用简单的Jackson代码将我的对象转换为json字符串,但速度非常慢。在我的机器上,仅转换一个对象就需要70毫秒。我做错了什么吗?
70毫秒来编码和发送一个小JSON消息是不可信的。毫无疑问,70毫秒的测量结果是你对代码进行基准测试的方式的产物。可能你没有考虑JVM预热效应。
所以,是的,你的基准测试做得不正确。可能。有关您可能犯的错误的更多信息,请参见:
- 如何在Java中编写正确的微基准测试? - 本答案的最后一部分。
现在我找到了三种方法来发送MyClass的实例:1:使用Jackson将其转换为byte []并发送。 2:使用内置序列化将其转换为byte []并发送。 3:将MyClass的成员转换为字符串,然后转换为byte []并发送。还有其他更好的解决方案吗?
理论上(即如果您拥有足够的技能,时间和耐心),最佳性能可以通过手动将数据编码为字节缓冲区并发送来实现。但这只是理论。
如果您正在寻找实际解决方案,并且这些解决方案可能比您尝试过的替代方案更快,请查看Google Protocol Buffers。据说它们很快...
但我怀疑您可能从您(可能)设计不良的基准测试中得出了错误的结论;请参见上文。我强烈建议在寻找更快的替代方案之前重新进行测试。
当我尝试发送一个对象时,需要70毫秒,但是当我尝试1000个对象时,只需要114毫秒,这不奇怪吗?
实际上,如果考虑JVM的工作方式,这一点都不奇怪。
当JVM启动时,它会加载您的代码并使用字节码解释器开始运行它。在代码被解释一段时间后,JVM运行JIT编译器为频繁调用的方法生成优化的本地代码。这个编译过程需要相当长的时间。
因此,当您测量发送一个对象所需的时间时,您可能真正测量的是发送一个对象和进行大量JIT编译所需的时间。但是那些JIT编译工作不需要重复执行。最终结果是处理一个对象似乎需要比处理1000个对象花费更长的时间。
JIT编译是常见的JVM预热效应之一,可能会扭曲编写不良Java基准测试的结果。

一个对象需要70毫秒,但如果我尝试1000个对象,只需要114毫秒,这不奇怪吗? 稍后我会查看Google Protocol... MyClass非常简单,只包含一些成员变量来存储要传输的数据。所以我只需构建一个字符串,例如:"1,100,abc",然后将其编码为字节,并实现解码方法。 - daddylonglegs
“这不奇怪吗?” - 不是的。这与一个设计很差的基准测试结果一致。 - Stephen C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接