16

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

我的第一个惊喜是这三种方法的速度有多慢。用户不想在手机上等待太久的结果,因此解析超过几十条记录的任何内容可能需要使用不同的方法。

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

4

8 回答 8

34

原始答案,2012 年

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

我刚刚做了一些性能测试,比较了 Android(和其他平台)上的解析器。被解析的 XML 文件只有 500 行左右(它是一个 Twitter 搜索 Atom 提要),但在三星 Galaxy S2 或摩托罗拉 Xoom2 上,Pull 和 DOM 解析每秒可以处理大约 5 个这样的文档。OP 使用的 SimpleXML(图表中的粉红色)与 DOM 解析最慢。

SAX Parsing 在我的两个 Android 设备上都快了一个数量级,管理 40 文档/秒的单线程和 65+/秒的多线程。

安卓 2.3.4:

Android上xml解析方式的性能对比

代码可在 github 中找到,并在此处进行讨论。

2016 年 3 月 18 日更新

好的,已经快 4 年了,世界已经在前进。我终于开始重新运行测试:

  1. 运行 Android 4.1.2 的三星 Galaxy S3
  2. 运行 Android 4.4.4 的 Nexus7 (2012)
  3. 运行 Android 6.0.1 的 Nexus5

在 Android 4.4.4 和 Android 6.0.1 之间,情况发生了巨大变化,我们有了一个新的赢家:Pull Parsing FTW 的吞吐量是 SAX 的两倍多。不幸的是,我不知道此更改何时到来,因为我没有任何运行 Android > 4.4.4 和 < 6.0.1 的设备。

安卓 4.1.2:

Android 4.1.2上xml解析方式的性能对比

安卓 4.4.4:

Android 4.4.4 xml解析方式性能对比

安卓 6.0.1:

Android 6.0.1 xml解析方式性能对比

于 2012-04-14T09:59:49.887 回答
5

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

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

Nexus 5:2055 毫秒

Galaxy Note 4:2498 毫秒

您可以通过链接找到更多基准报告: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

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

于 2015-04-09T15:17:10.797 回答
0

如果您从 Socket 解析它的 I/O 需要时间,而不是解析。尝试先使用数据,然后在加载后解析并测量性能。如果文件太大,请考虑使用一个非常大的缓冲区的 BufferedInputStream,这应该可以提高您的性能。

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

于 2011-08-28T23:53:15.093 回答
0

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

于 2011-08-28T23:01:56.593 回答
0

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

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

于 2011-08-28T22:29:51.527 回答
0

如果您在 XML 中解析日期,可能会显着减慢解析速度。随着 Android 的更新版本,这不再是一个问题(因为他们优化了时区信息的加载)

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

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

您提到您正在进行字符串比较,这也可能非常昂贵。也许考虑为您正在比较的字符串使用 HashMap,这可以带来明显的性能优势。

于 2011-08-28T22:30:42.137 回答
0

我们对 1MB XML 文件非常有效地使用了 pull-parser - 根据我的愿望,它们在大约 10-20 秒内被读取。所以如果你的代码没问题,速度也会很好。很明显,DOM 在有限的内存环境中非常慢,但 pull 或 SAX 确实不是

于 2011-08-28T23:45:56.453 回答
-1

与其使其成为同步过程,不如使其成为异步过程。您可以有一个按钮来启动 IntentService,它将为您处理数据并更新结果并在完成时显示通知。这样你就不会停止 UI 线程。

于 2012-03-03T18:53:34.360 回答