Home Noticias [lang_es]Rendimiento NRtfTree 0.3.0 beta2[/lang_es][lang_en]NRtfTree 0.3.0 beta2 Performance[/lang_en]

[lang_es]Rendimiento NRtfTree 0.3.0 beta2[/lang_es][lang_en]NRtfTree 0.3.0 beta2 Performance[/lang_en]

by sgoliver

[lang_es]

Una asignatura que tenía pendiente desde hace bastante tiempo era revisar el rendimiento de NRtfTree. Hasta ahora, este aspecto había quedado en un segundo plano por dos motivos principales:

  1. El tamaño de los documentos procesados no suele ser excesivo, lo que hace que el desempeño de la librería no tenga demasiada influencia.
  2. En las primeras versiones de la librería resultaba más interesante mejorar en primer lugar las características de la misma, aumentando las funciones disponibles y corrigiendo los errores detectados.

Sin embargo, mi intención con NRtfTree 0.3.0 es que por fin la librería consiga un nivel de madurez por encima de lo mínimamente aceptable, y para ello el rendimiento se convierte, esta vez sí, en un factor clave.

En cuanto a la velocidad de proceso de NRtfTree, el cuello de botella principal se encontraba sin duda en el lexer (clase RtfLex), un módulo que práctimente no se había tocado desde la primera versión de NRtfTee, allá por el año 2005. Analizando las posibles optimizaciones se han detectado dos problemas principales:

  1. Cada token generado definía e inicializaba sus propios objetos StringBuilder para el almacenamiento de los datos (palabras clave, parámetros y texto).
  2. El analizador consultaba (Peek) y leía (Read) repetidamente los mismos caracteres a la hora de procesar el fichero de entrada.

Ambos problemas se han solucionado fácilmente, definiendo un único StringBuilder a nivel de clase y reescribiendo el analizador de forma que tan sólo lea una vez cada caracter.

Para comprobar el grado de mejora provocado por estos cambios se utilizó un documento RTF sencillo (sólo texto) de 1.3 mb, obteniendo estos resultados respecto al tiempo de carga [ejecución del método RtfTree.LoadRtfFile()]:

Tiempo de Carga de Documentos

No, no hay ningún error, el gráfico anterior es correcto. Dos sencillos cambios en el analizador léxico han conseguido reducir en un factor de aproximadamente 96 veces el tiempo de carga de un documento, consiguiéndose un rendimiento realmente espectacular. Como información adicional, otras pruebas con documentos más complejos (texto+imágenes) de aproximadamente 3, 6 y 11 mb arrojan los siguientes resultados:

Documento Tiempo de Carga
3 mb 1.9646 seg
6 mb 4.5241 seg
11 mb 9.1274 seg

Como era de esperar, la relación entre el tamaño del fichero y su tiempo de carga es prácticamente lineal con el nuevo analizador léxico:

Los datos detallados de todas estas pruebas se pueden consultar en este enlace: pruebas rendiento NRtfTree beta1/beta2 [los datos corresponden a un programa sencillo que realiza 5 cargas consecutivas del mismo documento, previa ejecución forzada del recolector de memoria].

En cuanto al consumo de memoria de NRtfTree también se ha conseguido alguna mejora. Hasta la versión 0.3.0 beta1 cada nodo RTF inicializaba siempre su lista de nodos hijos, aunque no los tuviera. A partir de la beta2 esto dejará de ser así, y únicamente los nodos de tipo Grupo incializarán su lista de hijos, a menos que esto se haga de forma manual sobre un nodo de otro tipo. Tras algunas pruebas de carga de documentos, las diferencias entre la beta1 y la beta2 son las siguientes [tomando como ejemplo el documento anterior de 1.3 mb]:

Tipo de Objeto Creados Beta1 Tamaño Beta1 Creados Beta2 Tamaño Beta2
RtfTreeNode 23353 934120 23353 934120
RtfNodeCollection 23353 280236 2460 29520
RtfToken 25812 0 25812 0
RtfLex 1 12 1 12
RtfTree 1 32 1 32

La diferencia se encuentran en los datos marcados en rojo. Mientras que en la beta 1 se utilizan 280236 bytes para almacenar todas las listas de hijos, en la beta2 tan sólo se ocupan 29520 bytes. En total, tras la carga del documento, la beta1 utiliza 1214388 bytes para almacenar el árbol RTF, mientras que la beta2 usa 963672 bytes, lo que supone una reducción de más del 20% para este documento, una ganancia importante tratándose de un documento relativamente pequeño.

En resúmen, con la llegada de la versión de NRtfTree 0.3.0 beta2, hemos conseguido no sólo nuevas funcionalidades y la consolidación de otras funciones antiguas, sino que también se ha mejorado considerablemente el rendiento de la librería, consiguiendo así una versión realmente interesante.

[/lang_es]

[lang_en]

Since first public version, the objective of every new release of NRtfTree was to add new funtionality to the library. In NRtfTree 0.3.0 we also want to improve performance.

The main bottleneck in NRtfTree was the RTF lexer component (RtfLex class). While analyzing source code we dicovered two main problems:

  1. Each token define and initialize its own StringBuilder object to load keywords, parameters and text.
  2. The lexer Peek and Read the same characters repeatedly.

Both problems has been fixed in versión 0.3.0 beta2. RtfLex now define StringBuilder objects at class level and initialize them setting its lengh to 0 every time it starts a new token, and some methods has been rewriten to read characters only once.

This two simple changes result in a great performace improvement. In our tests, the load time of a simple RTF document (1.3mb, text only) was significantly reduced:

Load Time

Document Load Time

Yes, the chart is correct. Load time is now over 100 times faster.

Memory allocation has been improved too. In previous versions, each RTF tree node initialized its child node list, even if it had no children at all. In NRtfTree 0.3.0 beta2, only group nodes creates its children list (if node type is not GROUP, ChildNodes property is set to null).

In our tests, memory allocated by a simple RTF document tree (1.3mb, text only) was reduced in about 20%:

Object Created Beta1 Memory Beta1 Created Beta2 Memory Beta2
RtfTreeNode 23353 934120 23353 934120
RtfNodeCollection 23353 280236 2460 29520
RtfToken 25812 0 25812 0
RtfLex 1 12 1 12
RtfTree 1 32 1 32

[/lang_en]

You may also like

1 comment

Publicado NRtfTree 0.3 Final | sgoliver.net blog 06/08/2009 - 14:36

[…] ha eliminado un fragmento de código redundante en la clase RtfLex que debe ayudar a mejorar aún más el rendimiento de la librería al cargar un documento […]

Reply

Leave a Comment

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies