android xml xml-parsing saxparser simple-framework

Cómo resolver el problema de rendimiento del análisis XML en Android



xml-parsing saxparser (8)

Tengo que leer un archivo XML con aproximadamente ~ 4000 líneas en Android. Primero probé la biblioteca SimpleXML porque es la más fácil y tomó 2 minutos en mi HTC Desire. Así que pensé que SimpleXML es tan lento debido a la reflexión y toda la magia que utiliza esta biblioteca. Reescribí mi analizador y utilicé el método de análisis DOM incorporado con una atención especial para el rendimiento. Eso ayudó un poco, pero aún así tardó unos 60 segundos, lo que sigue siendo totalmente inaceptable. Después de un poco de investigación encontré este artículo en developer.com . Hay algunos gráficos que muestran que los otros dos métodos disponibles, el analizador SAX y el XML Pull-Parser de Android, son igualmente lentos. Y al final del artículo encontrarás la siguiente declaración:

La primera sorpresa que tuve fue la lentitud de los tres métodos. Los usuarios no quieren esperar mucho tiempo para obtener resultados en los teléfonos móviles, por lo que analizar algo más que unas pocas docenas de registros puede exigir un método diferente.

¿Qué podría ser un "método diferente"? ¿Qué hacer si tiene más de "unas pocas docenas de registros"?


Respuesta original, en 2012.

(nota: asegúrate de leer la actualización de 2016 a continuación)

Acabo de realizar algunas pruebas de rendimiento comparando analizadores en Android (y otras plataformas). El archivo XML que se analiza es de solo 500 líneas o menos (es un feed Atom de búsqueda de Twitter), pero el análisis de Pull y DOM puede producir aproximadamente 5 documentos por segundo en un Samsung Galaxy S2 o Motorola Xoom2. SimpleXML (rosa en el gráfico) como lo usan los vínculos OP para el análisis de DOM más lento.

El análisis de SAX es un orden de magnitud más rápido en mis dos dispositivos Android, administrando 40 subprocesos por segundo de un solo subproceso y 65 subprocesos de más por segundo.

Android 2.3.4:

El code está disponible en github, y una discusión here .

Actualización 18 de marzo de 2016

OK, así que han pasado casi 4 años y el mundo ha avanzado. Finalmente pude volver a ejecutar las pruebas en:

  1. Un Samsung Galaxy S3 con Android 4.1.2
  2. Un Nexus7 (2012) con Android 4.4.4
  3. Un Nexus5 con Android 6.0.1

En algún lugar entre Android 4.4.4 y Android 6.0.1, la situación cambió drásticamente y tenemos un nuevo ganador: Pull Parsing FTW con más del doble del rendimiento de SAX. Desafortunadamente, no sé exactamente cuándo llegó este cambio, ya que no tengo ningún dispositivo con Android> 4.4.4 y <6.0.1.

Android 4.1.2:

Android 4.4.4:

Android 6.0.1:


Con el analizador SAX, puedo analizar un archivo XML de 15,000 líneas en aproximadamente 10 segundos en mi HTC Desire. Sospecho que hay algún otro problema involucrado.

¿Estás poblando una base de datos desde el XML? Si es así, ¿recuerdas envolver toda tu operación de análisis en una transacción de base de datos? Solo eso puede acelerar las cosas en un orden de magnitud.


Creo que la mejor manera de trabajar con XML en Android es usar la biblioteca VDT-XML

Mi archivo XML contiene más de 60 000 líneas y VDT-XML lo maneja de la siguiente manera:

Nexus 5: 2055 milisegundos

Galaxy Note 4: 2498 milisegundos.

Puede encontrar más informes de referencia por enlace: VTD-XML Benchmark

Breve ejemplo de archivo 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>

Configuración del archivo "build.gradle"

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

Ejemplo de código fuente:

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); } } } } }

Resultado

Category ID = 20 Category Name = Fruit Category ID = 31 Category Name = Vegetables Category ID = 45 Category Name = Rice Category ID = 50 Category Name = Potatoes

Funciona para mí y espero que te ayude.


En lugar de convertirlo en un proceso síncrono, hágalo asíncrono. Puede tener un botón que inicie un IntentService que procesará los datos por usted, actualizará los resultados y mostrará una notificación cuando haya terminado. De esa manera no detienes el hilo de la interfaz de usuario.


Es muy difícil decirle por qué su código es lento sin verlo, y es muy difícil creer su afirmación de que la lentitud se debe al analizador XML cuando no ha proporcionado detalles de ninguna medida para demostrarlo.


Si está analizando Fechas dentro de su XML, eso puede ralentizar significativamente su análisis. Con las versiones más recientes de Android, esto se convierte en un problema menor (ya que optimizan la carga de información de la zona horaria)

Si tiene fechas que se están analizando y no las necesita, entonces puede usar un analizador SAX e ignorar cualquiera de los elementos de fecha.

O si puede cambiar su esquema XML, considere almacenar las fechas como enteros en lugar de cadenas con formato.

Usted mencionó que está haciendo comparaciones de cadenas, esto también puede ser bastante costoso. Tal vez considere usar un HashMap para las cadenas que está comparando, esto puede proporcionar notables beneficios de rendimiento.


Si su análisis desde un zócalo es la E / S que se está demorando, no el análisis. Intente consumir los datos primero, luego analizar una vez cargados y medir el rendimiento. Si el archivo es demasiado grande, considere un BufferedInputStream con un búfer muy grande, esto debería mejorar el rendimiento para usted.

Dudo seriamente que Simple XML demorará 2 minutos en cargar 4000 líneas, me doy cuenta de que un teléfono será mucho más lento que una estación de trabajo, sin embargo puedo cargar 200,000 líneas de XML en 600 ms en mi estación de trabajo.


estamos utilizando el analizador de extracción muy eficazmente para archivos XML de 1 MB, y se leen en unos 10-20 segundos en mi deseo. Así que si tu código está bien, la velocidad también lo estará. Es obvio que DOM es muy lento en un entorno de memoria limitada, pero Pull o SAX realmente no lo son