如何解决Android上的XML解析性能问题

时间:2011-08-28 22:12:30

标签: android xml xml-parsing saxparser simple-framework

我必须在Android上阅读大约约4000行的XML文件。首先我尝试SimpleXML library,因为它是最简单的,我的HTC Desire花了大约2分钟。所以我想也许SimpleXML因为反射和这个库使用的所有其他魔法而变得如此之慢。我重写了我的解析器并使用了内置的DOM解析方法,并对性能有一些特别的关注。这有点帮助,但它仍然需要大约60秒,这仍然是完全不可接受的。经过一番研究后,我找到了this article on developer.com。有一些图表显示其他两种可用方法 - SAX解析器和Android的XML Pull-Parser - 同样很慢。在文章的最后,您将找到以下声明:

  

我的第一个惊喜是这三种方法的速度有多慢。用户   不想在手机上等待很长时间,所以解析   任何超过几十条记录都可能要求采用不同的方法。

什么可能是“不同的方法”?如果你有超过“几十条记录”怎么办?

8 个答案:

答案 0 :(得分:34)

原始答案,2012年

(注意:请务必阅读下面的2016年更新!)

我刚刚对Android(和其他平台)上的解析器进行了一些性能测试。正在解析的XML文件只有500行左右(它是一个Twitter搜索Atom提要),但Pull和DOM解析可以在Samsung Galaxy S2或Motorola Xoom2上每秒大约翻译5个这样的文档。 OP中使用的SimpleXML(图表中的粉红色)与DOM解析最慢。

SAX解析在我的两个Android设备上的数量级更快,管理40个docs / sec单线程和65 + / sec多线程。

Android 2.3.4:

performance comparison of xml parsing methods on Android

code在github中可用,并且讨论here

2016年3月18日更新

好的,所以已经差不多4年了,全世界都在继续前进。我终于开始重新运行测试了:

  1. 运行Android 4.1.2的三星Galaxy S3
  2. 运行Android 4.4.4的Nexus7(2012)
  3. 运行Android 6.0.1的Nexus5
  4. 在Android 4.4.4和Android 6.0.1之间,情况发生了巨大变化,我们有了一个新的赢家:拉动解析FTW的速度是SAX吞吐量的两倍多。不幸的是,由于我没有运行Android>的任何设备,因此我不确切知道此更改的确切时间。 4.4.4和< 6.0.1。

    Android 4.1.2:

    performance comparison of xml parsing methods on Android 4.1.2

    Android 4.4.4:

    performance comparison of xml parsing methods on Android 4.4.4

    Android 6.0.1:

    performance comparison of xml parsing methods on Android 6.0.1

答案 1 :(得分:5)

我认为在Android上使用XML的最佳方法是使用VDT-XML library

我的XML文件包含超过60 000行,VDT-XML处理如下:

Nexus 5:2055毫秒

Galaxy Note 4:2498 milisec

您可以通过链接找到更多基准报告:VTD-XML Benchmark

XML文件的简短示例

 <database name="products">
        <table name="category">
            <column name="catId">20</column>
            <column name="catName">Fruit</column>
        </table>
        <table name="category">
            <column name="catId">31</column>
            <column name="catName">Vegetables</column>
        </table>
        <table name="category">
            <column name="catId">45</column>
            <column name="catName">Rice</column>
        </table>
        <table name="category">
            <column name="catId">50</column>
            <column name="catName">Potatoes</column>
        </table>
</database>

“build.gradle”文件的配置

dependencies {
    compile files('libs/vtd-xml.jar')
}

源代码示例:

import com.ximpleware.AutoPilot;
import com.ximpleware.VTDGen;
import com.ximpleware.VTDNav;


String fileName = "products.xml";

VTDGen vg = new VTDGen();

if (vg.parseFile(fileName, true)) {

     VTDNav vn = vg.getNav();
     AutoPilot table = new AutoPilot(vn);
     table.selectXPath("database/table");

     while (table.iterate()) {
        String tableName = vn.toString(vn.getAttrVal("name"));

        if (tableName.equals("category")) {
            AutoPilot column = new AutoPilot(vn);
            column.selectElement("column");

            while (column.iterate()) {
                 String text = vn.toNormalizedString(vn.getText());
                 String name = vn.toString(vn.getAttrVal("name"));

                 if (name.equals("catId")) {
                    Log.d("Category ID = " + text);
                 } else if (name.equals("catName")) {
                    Log.d("Category Name = " + text);
                 } 

            }
        }
     }
}

结果

Category ID = 20
Category Name = Fruit

Category ID = 31
Category Name = Vegetables

Category ID = 45
Category Name = Rice

Category ID = 50
Category Name = Potatoes

它对我有用,希望对你有所帮助。

答案 2 :(得分:0)

使用SAX解析器,我可以在HTC Desire上大约10秒内解析一个15,000行的XML文件。我怀疑还有其他一些问题。

您是否从XML填充数据库?如果是这样,您是否记得将整个解析操作包装在数据库事务中?仅这一点就可以将事情提高一个数量级。

答案 3 :(得分:0)

如果要解析XML中的日期,这会严重降低解析速度。随着Android的更新版本,这变得不那么成问题(因为他们优化了时区信息的加载)

如果你有正在解析的日期并且你不需要它们,那么你可以使用SAX解析器并忽略任何Date元素。

或者,如果您可以更改XML架构,请考虑将日期存储为整数而不是格式化字符串。

你提到你正在进行字符串比较,这也可能非常昂贵。也许考虑对你要比较的字符串使用HashMap,这可以提供显着的性能优势。

答案 4 :(得分:0)

很难告诉你为什么你的代码在没有看到你的代码的情况下很慢,并且当你没有提供任何测量的详细信息来证明这一点时,很难相信你的断言是因为XML解析器的缓慢。

答案 5 :(得分:0)

我们对1MB XML文件非常有效地使用了拉解析器 - 并且在我的欲望中大约10-20秒读取它们。所以,如果您的代码没问题,速度也会如此。显然DOM在有限的内存环境中非常慢,但是拉或SAX确实不是

答案 6 :(得分:0)

如果从Socket解析它的I / O花费时间,而不是解析。尝试首先使用数据,然后在加载后解析并测量性能。如果文件太大,那么考虑一个带有非常大缓冲区的BufferedInputStream,这可以提高你的性能。

我非常怀疑Simple XML需要花费2分钟来加载4000行,我意识到手机比工作站慢很多,但是我可以在600ms内加载200,000行XML工作站。

答案 7 :(得分:-1)

不要将其作为同步过程,而是使其异步。您可以使用一个启动IntentService的按钮来为您处理数据,并在结束时更新结果并显示通知。这样你就不会停止UI线程了。