【问题标题】:Java marshaller performanceJava 编组器性能
【发布时间】:2011-01-29 14:37:06
【问题描述】:

我使用 JAXB Marshaller 以及我自己的 marshaller 将纯 java bean 对象编组为 XML。据观察,它们都需要几乎相同的时间来编组。性能不可接受,需要改进。有哪些可能的方法可以提高编组器的性能?喜欢线程?

【问题讨论】:

标签: java performance multithreading jaxb marshalling


【解决方案1】:

确保只创建一次 JaxB 上下文实例,创建上下文需要一些时间,因为它使用反射来解析对象的注释。

请注意,JAXBContext 是线程安全的,但 marshallers\unmarshallers 不是,因此您仍然必须为每个线程创建 marshaller。但是我发现当你已经拥有一个 jaxb 上下文时创建编组器非常快。

【讨论】:

  • 感谢您的评论,大大加快了我的 junit 速度。 Jaxb 上下文生成对我来说需要 14 多秒。在那之后虽然元帅/解组非常快解组:0.116s 元组:0.023s
  • 从 JDK 8u192 开始,这仍然非常重要。它将 100MB XML 的保存时间缩短到几秒钟。
【解决方案2】:

支持 JibX 的使用。和 questzen 一样,我在性能测试中发现 JibX 比 JAXB 快 9 倍。

另外,使用 JibX 时,请确保类路径中有 woodstox。我发现woodstox 的 Stax 实现比 Java6 的 Stax 实现快大约 1050%。

【讨论】:

  • 没有反对 JibX,但从我所见,9x 似乎相当高。 JAXB 对我来说非常高效,只要您使用 Woodstox,不要使用验证(Jibx 不会这样做,而且很少用于编组)。而且,如果可能的话,不要使用版本 JAXB impl JDK 包:使用最新版本。
  • 实际上,想一想,我确实记得 Sun 的 Stax 包 (Sjsxp) 在编写 XML 方面比 Woodstox 慢得多——这可以解释 9 倍的差异,假设 JibX 使用 Woodstox(确实如此)默认为)
【解决方案3】:

除了其他好的建议,我认为您使用 JAXB 的方式有问题——只要:

  • 您使用的是 JAXB 版本 2(永远不要使用过时的 JAXB 1 —— 那是非常缓慢、无用的废话);最好是来自http://jaxb.dev.java.net 的最新 2.1.x 版本
  • 确保您使用 SAX 或 Stax 源/目标;切勿使用 DOM,除非出于互操作性的绝对必要:使用 DOM 会使其速度降低 3 到 5 倍,而且没有任何好处(它只是使对象模型翻倍:POJO -> DOM -> XML;完全不需要 DOM 部分)
  • 理想情况下使用最快的 SAX/Stax 解析器; Woodstox 比 Sun 捆绑的 Stax 处理器快(而且 BEA 的 ref. impl. 有问题,不比 Sun 快)

如果 JAXB 仍然比手动编写的变体慢 50% 以上,我会对其进行分析以查看还有什么问题。如果使用得当,它的工作速度不会很慢——我已经连续测量过它,发现它的速度非常快,以至于手写转换器通常不值得花时间和精力。

顺便说一句,Jibx 也是一个很好的软件包,所以我不反对尝试它。它可能仍然比 JAXB 快一点;如果两者都正确使用,则不是 5 倍或 10 倍。

【讨论】:

    【解决方案4】:

    如果编写大型 XML 树,则向 javax.xml.bind.Marshaller.marshal(Object jaxbElement, java.io.OutputStream os) 方法对我的情况有很大影响:

    编写一个 100MB 的 XML 文件所需的时间可以从 130 秒减少到 7 秒。

    【讨论】:

      【解决方案5】:

      根据我的经验,JIBX http://jibx.sourceforge.net/ 比 JAXB 快近 10 倍。是的,我测量了它的性能规格。我们用它来绑定带有大型 HL7 xml 的 java bean。话虽如此,提高性能的方法不是依赖模式定义,而是编写自定义绑定。

      【讨论】:

        【解决方案6】:

        我们刚刚发现了一个与 Xerces 使用的默认解析器配置相关的 JAXB 性能问题。一个数据文件 (

        引用“如何更改默认解析器配置?”来自http://xerces.apache.org/xerces2-j/faq-xni.html

        DOM 和 SAX 解析器按以下顺序决定使用哪个解析器配置

        1. 查询 org.apache.xerces.xni.parser.XMLParserConfiguration 系统属性以获取解析器配置的类名。
        2. 如果 JRE 安装的 lib 子目录中存在名为 xerces.properties 的文件并且定义了 org.apache.xerces.xni.parser.XMLParserConfiguration 属性,则将从文件中读取其值。
        3. 从 META-INF/services/ 目录请求 org.apache.xerces.xni.parser.XMLParserConfiguration 文件。该文件包含解析器配置的类名。
        4. org.apache.xerces.parsers.XIncludeAwareParserConfiguration 用作默认解析器配置。

        使用 JAXB 解组会导致重复应用此算法。因此可以花费大量时间反复扫描类路径,寻找不存在的配置文件。修复方法是执行选项 1、选项 2 或选项 3(在 META-INF 下创建配置文件)。任何可以防止重复的类路径扫描。

        希望这对某人有所帮助 - 我们花了几天时间才找到它。

        【讨论】:

          【解决方案7】:

          我们可以通过在系统级别设置快速启动属性来实现编组和解组的性能。这将大大提高性能。

          System.setProperty("com.sun.xml.bind.v2.runtime.JAXBContextImpl.fastBoot","true");

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-11-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-03-19
            • 2010-09-22
            相关资源
            最近更新 更多