Los problemas de la utilización y reutilización de muchos objetos de diferentes tamaños en una aplicación puede causar la fragmentación del montón que puede ralentizar la velocidad de procesamiento. Este artículo utiliza una fábrica de objetos, de hacer y reciclar los objetos con un mínimo de efectos de la fragmentación.

Uno de los patrones en el libro clásico "patrones de diseño; elementos reutilizables de software orientados a objetos" es el método de la fábrica, donde los objetos se crean y recientemente he tenido que utilizarla. ¿La razón? Un problema de la fragmentación de la memoria en un sistema de simulación utilizando un gran número de objetos de celebrar arreglos numéricos. Hay varios tipos de matriz numérica, en los tamaños fijos que van de 1500 x 1 a 5000 x 10 números, ya sea enteros o dobles. Estos se utilizaron en una simulación de un cálculo financiero durante un período de dos años, la creación de datos sobre cada uno de simulación de 472 días a partir de datos históricos. En cada día, se dio lectura de datos desde una base de datos, procesados y, a continuación, salvado a cabo.A pesar de las amplias de control de fugas, el software sólo para ejecutar un número de días simulados antes de comer el fichero de intercambio de Windows. Pérdidas de memoria fueron cuidadosamente rastreado y eliminado, pero mi pelo estaba aún en peligro. La aplicación no iría más allá de unos 30 días antes de simular que se había comprometido más de la mitad de la del archivo de paginación NT-este en un 512 MB de RAM del sistema! Cierre investigación puso de manifiesto que cada día se corrió, la memoria creció a partir de 5M a alrededor de 80 MB a continuación reducir a volver de nuevo sobre 5M. En la cara de la misma, no un problema 512Mb con el para jugar, pero viendo el Win NT Administrador de tareas cada vez más mostró una cantidad de memoria comprometida.

FRAGMENTACIÓN
El problema era simple, era el montón de culpar a la fragmentación. Esto ocurre cuando diferentes objetos se crean y luego destruido en repetidas ocasiones. Como cada objeto se crea, consume la memoria del montón. Si los objetos fueron creados y luego destruidos en orden inverso que probablemente no sucederá ya que todos los liberados de memoria podrían fusionarse en un gran bloque. Pero, en cualquier sistema con un gran número de objetos de la orden de la creación y la destrucción nunca será simétrico-mi aplicación puede tener hasta 50.000 objetos en memoria al mismo tiempo. Así que cuando un objeto es destruido, un puntero a la liberados bloque de memoria se añade a un bloque de libre lista.Cuando otras solicitudes de memoria se hacen, Windows trata de asignar esas solicitudes fuera de la lista de liberados en primer lugar. La fragmentación sucede cuando un gran bloque de 1Mb como se ha solicitado y posteriormente liberado, seguido por una solicitud de un bloque más pequeños. Esto está tomado de la primera manzana a la libre-lista que puede muy bien ser el 1Mb, lo que deja libre sólo 900KB. Luego, otra solicitud de un gran bloque de 1Mb viene, no puede ser satisfecha a partir de la lista libre y por lo que se ha tomado de la pila. Si la creación / destrucción del ciclo ocurre la suficiente veces grandes bloques en el montón son picados en pequeños trozos, la memoria RAM física está agotada y se sustituye con RAM virtual. Windows montón de gestión de memoria (y Delphi) es muy inteligente-que se necesita mucho para llegar a fragmento. Pero bajo la presión implacable de un gran número de objetos creados y destruidos, el administrador de memoria gradualmente cueva pulg

Cuando Windows se ejecuta de ram libre, que se inicia el canje de páginas de memoria RAM y el disco tiene un rendimiento de la nariz de buceo. Su aplicación puede ser galopante a lo largo de felices al 100% de CPU hasta que se inicia el intercambio. A continuación, se convierte en un funeral de rastrear a lo largo de marzo tal vez en 7-10% de CPU, teniendo siempre a correr. Desastres!

Microsoft ha puesto un gran esfuerzo hacer que el administrador de memoria sea lo más eficiente posible. Por ejemplo, en virtud del NT, hay un proceso de dos etapas de la reserva y la comisión de la memoria. Si su aplicación requiere de 100Mb, es reservado cuando la aplicación se ha cargado. Pero sólo cuando la memoria se accede a la reserva son las páginas cometido. Si desea aprender más de lo que posiblemente nunca se necesita saber acerca de este y otros temas, recomiendo el libro Dentro de NT, publicado por Microsoft Press, pero obtener la versión de David Salomón, que es la edición más tarde, no Helen Custer primera edición.

FÁBRICA DE MODELO
Por lo tanto, no necesitan una forma de fragmentar la creación de muchos objetos, con ellos, tirar a la basura y luego hacerlo de nuevo todas las ventanas sin correr de la memoria virtual. Después de haber leído recientemente el libro Plan pensé ¿por qué no utilizar una fábrica, es decir, una fábrica de objeto que crea los objetos de una determinada categoría. Entonces fue un mejor y que el medio ambiente, por lo que llega a reciclar todos sus objetos manufacturados en lugar de destruirlos y sin la fragmentación de los problemas asociados. La guinda del pastel fue a hacer la fábrica en condiciones de ampliar su capacidad sin pérdida de velocidad de acceso.

En lugar de tener una fábrica de clase para todos los tipos de clase, tomé el enfoque más sencillo pasar de la clase de objeto en la fábrica como la creación de una fábrica de parámetro. Cuando la fábrica se crea que especificar tanto la clase de objetos que puede hacer y la capacidad de almacenamiento inicial de la fábrica. Este tamaño se puede modificar al alza llamando a la GrowFactory método. Le sugiero que sólo llaman a esto en circunstancias excepcionales (!) Las circunstancias.

El enlace de vuelta a la fábrica de cada objeto que se necesita, por lo que todos "fábrica de objetos" (FMOs) deben descender de un TFactoryObject clase en lugar de TObject. Esto añade una fábrica de referencia que es "el sello", en todos los FMOs a fin de que el objeto sabe que fábrica para uso propio a reciclar.

En lugar de crear un objeto de su aplicación solicita un adecuado de la fábrica llamando a su RequestObj método que devuelve un objeto tclass atrás y convertir a la derecha usando la clase 'como'. Por último cuando haya terminado de usar el objeto que acaba de llamar a su método RecycleSelf. No creación o destrucción, excepto las fábricas de sí mismos.

¿Cómo funciona?
Cuando la fábrica se crea, todos los objetos físicos son creados en un bloque contiguo de memoria RAM. A TList (fblocklist) objeto almacena la dirección de cada uno de estos bloques. Cada vez que crezca la fábrica, un nuevo bloque se ha creado y añadido a esta lista. El método AddObjects crea el número especificado de objetos utilizando el carnero del bloque. Si escribe este código como ser conscientes de que sólo haciendo un TObject (dirección) no es suficiente para crear el objeto. Usted siempre debe llamar ObjectClass.InitInstance (dirección) para convertirlo en un "buen" objeto. InitInstance borra todo a cero, cero, etc, pero que es más importante que en ella se establece el VMT.

La fábrica también contiene otro TList (ffreelist), que tiene la dirección de cada objeto no utilizados.

Todo el burro de trabajo de llenado de la fábrica se realiza en el método privado AddObjects. Para cada objeto creado en el bloque, esto convierte el puntero ptr en un objeto, utilizando FactoryObject como la clase de objeto creado. Este debe ser siempre un descendiente de TfactoryObject. Obj tiene el objeto de referencia y enlaces de la fábrica a los objetos fabricados. ptr se incrementa al punto que el próximo objeto en el bloque, añadiendo fsize.

Para obtener un objeto que r código Request_Obj pide que aparecerá la referencia fuera de la final de la ffreelist y lo devuelve como el primer objeto solicitado. El reciclado es a la inversa, que empuja el objeto reciclado de referencia en la final de ffreelist. Una cosa a tener en cuenta. Cuando un objeto fabricado fábrica está en uso, la fábrica no tiene ninguna referencia a la misma, aunque la memoria ocupada por el objeto está contenido dentro de la fábrica!

La sustitución de crear y destruir
Uso de la fábrica requiere el uso de objetos manufacturados ligeramente diferente de lo normal. Ya no crear o libre en forma explícita, en lugar que acaba de solicitar la fábrica para el objeto. A menos que la fábrica está vacía siempre este trabajo. Tienes que modificar el código de inicialización en el constructor y la terminación de código en el destructor rutinas. Hay dos enfoques.

1) Si el objeto tiene crear un simple constructor sin parámetros, puede cambiar el nombre al procedimiento de inicio; anular y eliminar cualquier heredado crear las llamadas. La fábrica siempre pide un método de inicio de cualquier objeto cuando se solicita. Por defecto, esta no hace nada, pero puede anular este modo que su inicio se llamará automáticamente en cada objeto se solicita a la fábrica.
2) Si el original ha de crear los parámetros, cambie el nombre a algo así como Inicializar y eliminar las llamadas heredado etc. Después de que el objeto se solicita llamar a la rutina inicializar, por ejemplo, MyRoutine.Initialise (...)

Si el objeto ha destructor código, cambiar el nombre al procedimiento de Hecho; anular de modo que se llama automáticamente cuando el objeto se recicla. Hecho de inicio y son similares para crear / destruir, pero sin el equipaje de la construcción o destrucción mecanismo.

Como una pequeña digresión, yo entiendo que hay argumentos de Delphi en el mundo en favor de una parte o la creación de dos parte la primera parte es donde el constructor tiene parámetros completamente y establece el objeto. En el enfoque de dos parte, el constructor sólo crea un objeto en blanco que luego se inicializado por un método más tarde. La fábrica de enfoque creo que es firmemente en los dos-parte campamento de ..

Cuando la fábrica se destruye, todos los bloques de memoria asignados son liberados. Antes de esto, la fábrica comprueba que el número de objetos en el freelist partidos de la capacidad. Si te has olvidado de reciclar todos sus objetos de restante, se plantean una excepción.

Programa de Comparación
Esto demuestra los beneficios de las fábricas .. En el trabajo de mi aplicación había muchos diferentes tamaños de los objetos en diferentes cantidades, pero una línea 15000 programa no es exactamente ser publicable. Después de un poco de ensayo y error hasta que vine con un corto programa que puede mostrar la fragmentación. Sin embargo, esto depende del tamaño de los diferentes objetos, cuántos hay, RAM disponible y por cuánto tiempo se ejecuta. Asimismo, la fragmentación parece ocurrir más rápidamente en NT4.0 el 98 lo que sugiere que tal vez 98 ha un mejor gestor de memoria. Cuando se ejecuta crea y destruye un gran número de objetos en repetidas ocasiones por el número de días especificado. Asimismo, hace exactamente lo mismo utilizando una fábrica. Cada día es el tiempo y ambos conjuntos de trazado veces utilizando Tchart.He utilizado tres tipos de objetos, todos los descendientes de tTestobj que desciende de Tfactoryobject. Objetos pequeños son 2K en tamaño, son medianas y grandes 40K son 800 K, pero estos tamaños se definen por las constantes y pueden cambiarse fácilmente. El programa asigna demo de 100Mb para el normal y otro objetos de 100Mb para la fábrica. Ambos contienen el mismo número de objetos-dividido en partes iguales por tamaño entre los tres tipos de objetos por lo que hay 17.406 objetos pequeños, 873 medianas y 43 grandes. En el procedimiento de creación de objetos TimeOneDay estos son creados al azar, y añadió a la lista. Al final del día en que son liberados y el proceso repetido día siguiente.El mismo se realiza a través de tres fábricas con todos los objetos fabricados añadido a una lista factorydata. En un P2 400 con 256 MB de funcionamiento durante 100 días, hubo un modesto incremento en el tiempo tanto para la fábrica y la creación de objetos normales. Comentando la creación normal confirmó esta sospecha-el aumento fue mucho menos más de 1000 días un plazo utilizando en contra de las fábricas de 100 días con ambos normal y las pruebas de fábrica. Me imaginó que este fue causado por el aumento de canje de la página debido a la fragmentación que afectan a ambos procesos. Algunas otras combinaciones de tamaños y número de objetos en Windows 98 no mostró la fragmentaciónI aplicado este principio utilizando una TList para ambos testdata y factorydata y cambió más tarde cuando me di cuenta de que en repetidas ocasiones y la adición de la liberación de 18.000 referencias también se suma a la fragmentación del montón. No estoy abogando amaraje tstringlists completamente en el código-que son muy útiles (como se tlists), pero si tiene que manipular un gran número de temas, tal vez sería mejor utilizar su propia lista de las estructuras. Si desea utilizar o TList TStringList para este propósito, probablemente su mejor llenar completamente la estructura con punteros nulos, de modo que count = capacidad y uso de un entero a celebrar el índice de la última puntero.

Esta aplicación también confirmó que el código de fábrica es muy rápido en la asignación y supresión-30 ms normalmente de 18.000 objetos en lugar de los 870 ms normal que la creación / eliminación tomó.

------------------------------------------------

Tgis artículo apareció originalmente en la revista para desarrolladores Delphi. Sources.zip

Average rating: