Monitorizar el uso de memoria de nuestras aplicaciones .NET

En aquellas aplicaciones de cierto tamaño, donde el consumo de memoria se convierte en un tema a tener en cuenta, es importante que se considere el consumo de memoria desde las primeras fases de diseño de la aplicación, o las consecuencias después serán peores y más difíciles de arreglar, como veremos a lo largo del presente artículo. Típicamente, las aplicaciones se pueden clasificar en pequeñas (<20Mb e consumo de memoria RAM), medianas  entre 20Mb y 50Mb) y grandes (>50Mb). Cuanto mayor es el consumo de memroria de una aplicación, más  mportante es tenerlo en cuenta desde las primeras fases de diseño de dicha aplicación.

¿Cómo afecta el uso de memoria al desempeño?

Recordemos que un computador normal tiene al menos 3 niveles de memoria: L1 y L2 que son típicamente cachés on-chip, de baja capacidad y muy rápido acceso, una posible L2 on-board y la propia memoria RAM. Después está el disco, pero si estamos contando con él como sistema de memoria estamos perdidos, pues su velocidad de acceso es  0.000 veces más lento que el de una RAM.

Existen tres tipos de cuellos de botella a tener en cuenta para toda aplicación:
– Rutas de acceso a datos que se utilizan continuamente, y que deberán ser traídos continuamente como operandos a las cachés. Si estos conjuntos de datos son muy grandes, no podrán ser ubicados en las cachés de una forma más o  menos permanente y útil para el desempeño.
– Primer arranque de una aplicación. Lo que se conoce como “arranque frío”. El problema de este arranque es que  todos los datos del programa deben ser traídos de disco. El desempeño se ve afectado aquí por los datos e  instrucciones que utiliza el propio programa, no la memoria que va a utilizar, el montículo o la pila de llamadas, detalles que son gestionados por el sistema operativo.
– Cambios de aplicación. En un entorno típico multitarea donde conviven varias aplicaciones en memoria y se dan los fenómenos de concurrencia y planificador en la CPU, cada vez que se cambia de aplicación por parte del usuario para trabajar en dicha aplicación se produce un robo de memoria entre aplicaciones, lo cual se traduce en un intercambio a disco de las páginas que deben ser desalojadas para que sean utilizadas por la nueva aplicación que tiene el “foco”. Este consumo afecta no solamente a los datos del programa e instrucciones como ocurría en el caso anterior, sino a  toda la memoria que utiliza un programa, pues las páginas que se trasladan contienen datos, pila, etc.

¿Qué puedo hacer para mejorar el consumo de memoria de mis aplicaciones?

Existen tres modos en los que se puede pellizcar un poco el uso de memoria. Todos ellos se ven afectados por el  diseño de los propios algoritmos, que son los que dictan cómo se accede a memoria.
– Ejecutar menos código al inicio, lo cual favorece el arranque frío.
– Tocar menos datos, lo cual favorece el primer factor que explicamos antes.
– Modificar las estructuras de datos para utilizar otras más eficientes, que también favorece el primer factor.

La mayor parte de las veces lo que se suele hacer es optar por la tercera solución, lo cual implica retocar sensiblemente el código, con los costes que ello conlleva, no sólo de rediseño, y desarrollo sino que también de  testing. Es por esto por lo que es importante pensar en la eficiencia de la memoria desde las primeras fases de desarrollo si preveemos un consumo de memoria importante, porque luego pueden venir los problemas.

Monitorizando procesos

Para monitorizar procesos, se puede utilizar el Task Manager como primera aproximación. Esta herramienta nos aportará valiosa información de cada proceso, como PID, memoria compartida y memoria privada.

La memoria compartida de un proceso se refiere generalmente a las instrucciones, que son de sólo lectura. La  memoria privada, por otro lado, está constituida principalmente por los datos locales de cada proceso, que son datos de lectura y escritura. Sin embargo, hay un tipo de memoria que no aparece en el Task Manager y que hay que tener en cuenta, precisamente porque es el mayor cuello de botella de todo proceso: el sistema de ficheros. Cada vez que se accede al sistema de ficheros se incurre en una penalización notable en el rendimiento del proceso que en muchos casos es inevitable.

Otra herramienta más avanzada para la monitorización del uso de memoria es VADump, que aporta información hasta el nivel de DLL’s.
En el artículo que se referencia más abajo encontrará más información acerca de esta herramienta.

El recolector de basura de .NET.

El recolector de basura elimina regiones de memoria que no son utilizadas más por un proceso. Existen algunas posibilidades de manipulación del recolector que permite mejorar el consumo de memoria. Para ello hay que entender cómo se organiza dicho recolector en .NET.

Una optimización muy importante es que el GC no busca en todo el montículo de objetos cada vez que es ejecutado, sino que divide el montículo en tres “generaciones”:

– GC0: la más pequeña y rápida, solamente busca candidatos a limpiar entre las nuevas localizaciones ocupadas de memoria tras la última pasada del GC. Idealmente, el tamaño de esta generación es menor que la L2.
– GC1: selecciona las localizaciones que sobrevivieron a la última pasada del GC. Es más lento de ejecutar que la GC0.
– GC2: recorre todos los objetos. La más lenta, por tanto, de hecho el tiempo que tarda en pasar es significativo. Este tiempo que tarda en recorrer todos los objetos crece de una forma más o menos lineal con el tamaño del montículo. El coste real depende de la cantidad de memoria que sigue estando ocupada por el proceso, el número de punteros del GC a dicha memoria y cómo de fragmentado esté el montículo.

Una herramienta que permite monitorizar con precisión el uso del GC es PerfMon. Para más información acerca de dicha herramienta, léase el artículo que se referencia al final.


Referencias:
“Memory Usage Auditing for .NET Applications”
Subramanian Ramaswamy & Vance Morrison
MSDN Magazine
June 2009

Antipatrones: el blob

Sigo leyendo e informándome acerca de patrones. El libro que estoy leyendo, cuyo título aparece referenciado al final del artículo, es de los mejores que he leído de informática y gestión de proyectos, estoy encontrando cosas muy interesantes y creo que se le puede sacar bastante partido. Publicaré todos los antipatrones que pueda, al menos los que encuentre más ilustrativos y curiosos.

El Blob (*)

Yo lo llamo el “monstruo” o el “bicho”, porque viene a ser precisamente eso, una cosa gigantesca y poco manejable. Una evidencia de que estamos ante la presencia de un Blob es cuando alguien dice “esta es la clase que representa el núcleo de la arquitectura“. Malo. Desconfiar de ello.

El blob se encuentra en sistemas donde una clase monopoliza el procesamiento y el resto de las clases básicamente se limitan a encapsular datos. El problema es que la mayoría de las responsabilidades están contenidas en una sola clase. Esto provoca que modificar el blob implique modificar otras muchas clases.

Al final, el blob se convierte en una clase procedural disfrazada de orientación a objetos. Puede ser resultado de una localización inapropiada de los requisitos. Suelen aparecer como clases controladores o manejadoras / gestionadoras.

También puede aparecer en prototipos evolutivos, al crecer éstos. No se reparten responsabilidades y un módulo va asumiendo todo. Además, debido al mantenimiento, se va acumulando código útil mezclado con código que ya no sirve para nada. Esto mismo se da en sistemas incrementales, por la misma razón.

Síntomas

– Clases con muchos atributos y/o métodos.

– Dispar colección de atributos / métodos sin aparente relación entre sí (falta de cohesión).

– Una única clase controladora asociada con clases simples de datos.

– Ausencia de diseño orientado al objeto. El blob parece más bien un Main().

– Un diseño legado que no ha sido correctametne refactorizado en una arquitectura orientada a objetos.

Consecuencias

– El blob es típicamente demasiado complejo como para ser reutilizado y probado.

– Puede afectar gravemente al rendimiento al cargar un objeto tan grande en memoria probablemente utilizar un gran número de recursos.

Causas

– Falta de arquitectura orientada al objeto, o de una arquitectura consistente y estable en general.

– Intervención limitada: cambios en el código tienden  a añadir sobre lo que ya hay, en lugar de crear nuevas clases y rediseñar / refactorizar.

– Especificación inadecuada: captura de requisitos incompleta o no adecuada.

No es una mala práctica porque…

Es aceptable cuando se adaptan sistemas legados no orientados a objetos. No se requiere refactorizar el código, sino hacerlo más accesible al sistema legado.

Solución refactorizada

Mover código fuera del blob. Identificar y categorizar atributos y operaciones, según la cohesión. Buscar alojamiento para dichos atributos y métodos en clases apropiadas. Eliminar redundancia en las asociaciones que ya no son necesarias y reducir el acoplamiento. Extraer herencia y abstracción allí donde sea necesario. Estudiar las comunicaciones entre clases, paso de parámetros, etc.

Variaciones

– Transformar el blob en una clase coordinadora, que gestiona cómo hacen el trabajo los demás, delegando dicho trabajo en las clases de este modo coordinadas. De manera que el blob no es un ejecutor, sino un coordinador.

– El blob puede presentarse también como un centro de almacén de datos compartido por muchas clases, aunque no realice procesamiento alguno con dichos datos;  algo así como un repositorio de datos en memoria, una sección de memoria compartida gigantesca e inapropiada.

(*)No confundir con el tipo de datos para el almacén de objetos binarios en una base de datos; no tiene nada que ver.


Referencias:

Anti Patterns – Refactoring Software, Architectures and Projects in Crisis, varios autores.

De artistas, cantantes y cantamañanas

La última polémica de este Gobierno que tantas polémicas suscita en la Red y tantas líneas me permite rellenar en este blog (gracias, Presi), está en los derechos de autor e Internet. Bueno, no es la última ya que está el caso Haidar al que quizá dedique otras cuantas líneas, pero hoy hay otros pitos que tocar.

Al margen de manifestaciones, gente en la calle, un sinfín de blogs y portales publicando un manifiesto al cual apoyo y demás escándalos, fue realmente impresionante ver a una pandilla de vagos de abrigo de bisón y chalé en la Moraleja diciendo que “se mueren de hambre”. Con la que está cayendo. Familias en paro, hipotecas, créditos, deudas, EREs y demás temario y cuatro muerdealmohadas se quejan de que “se mueren de hambre”… escuece sólo oirlo.

Quizá es que cuando se lleva un modelo de vida en el cual los lujos están a la orden del día, ir al spá, a la sauna, bañarse en la piscina, tomar baños de rayos UVA y daiquiris varios, resulta que cuando vienen mal dadas y hay que comprar yogures de Hacendado jode un montón. Yo les comprendo, señores “artistas”, su “arte” vale mucho, mucho más que los cuadros de Picasso, Van Gogh, Goya o Sorolla. Ellos no cobrando por cada foto que aparece en los libros de arte, ni por los muchos cuadros que se han inspirado en aquellas magistrales obras, pero es que no les llegan a ustedes ni a la suela de los zapatos; donde esté un “uyuy mi gato hace uyuyuyuyuyy” de Rosario Flores que se quite Dalí, Mozart y la Filarmónica de Berlín.

De hecho, deberían patentar dichas expresiones y de este modo, cada vez que alguien diga “uyuyuy”, “depende” o “tengo el corazón partío” les pague a ustedes un plus. Qué coño, deberíamos pagarles un plus en cualquier caso, porque aunque no lo digamos, seguro que lo hemos pensado, que la gente es mú mala. Cada vez que un grupo componga una sola canción en la que algún acorde recuerde a alguna tonadilla de Bunbury, debería pagarle a éste un… un momento, no, bueno, esto mejor no, que Bunbury ya tiene sus propias fuentes de inspiración, perdone usted, Enrique.

El caso de Bunbury me jode profundamente, porque todavía recuerdo oírle aquello de “la piratería y las descargas no acabarán nunca con la música; acabarán con la industria discográfica, que es muy distinto; pero puede retornarse a algo como lo que ocurría con los juglares en la Edad Media, a la música en vivo, que al fin y al cabo es la música de verdad, y es donde de verdad se ve si un músico vale o no vale”. No voy a citar la fuente porque la desconozco, y este texto no es exactamente como lo dijo, pero les puedo asegurar que dijo semejante belleza. Y ahora apoya a sus coleguis de compaña. No sé si es por apoyar a un amigo en estos duros momentos de profunda demagogia (artistas comunistas reconvertidos al más puro capitalismo-socialismo) o es que este tipo es un redomado hipócrita. De verdad que me jode hacer una crítica tan insultante de alguien a quien admiro musicalmente, pero es que lo que no está bien, no está bien. Y hay mucho músico por ahí que ante su público dice una cosa y luego actúa de forma muy diferente.

Pero vamos al meollo, porque al final se está consiguiendo lo que todo político desea, ya veo a ZP y a Rajoy frotándose las manos: que la sociedad se enfrente entre sí. Cuando a un hombre lo presionan, éste se rebela, y no dudo que los artistas estén presionados, en ningún modo. La puta demagogia que vivimos día a día hace que las víctimas de nuestras preocupaciones seamos nosotros mismos, o nuestro prójimo si se me entiende mejor, y nos demos de hostias en cruel guerra civil en lugar de buscar a los auténticos responsables: políticos y empresarios capitalistas que se forran a costa del talento de otros.

Y lo que ocurre es que Internet (de momento y gracias a Dios) es libre de todo esto. Internet nos hará libres, muchachos. Internet no entiende de capitalismos, demagogias y otra cosa que no sea libertad de expresión. Por ello Internet les toca tanto la moral a esos empresarios de Montecristo en ristre y Longines en muñeca. Y la consecuencia de nuestra rebelación, de nuestra lucha por la libertad la pagaremos nosotros, en forma de cánones y leyes que se basan en dar leña al ciudadano y limitar su libre albedrío.

Que no, señora Sinde, que no voy a ir a ver ni una puñetera bazofia que se llama cine español en el cual sólo se ven tetas y culos sin argumento y sin sentido, que no quiero ver esa porquería ni gratis, películas subvencionadas que en el mejor de los casos han llegado a las carteleras y en el peor de los casos no han llegado ni a rodarse (¿dónde está la pasta de la subvención, entonces?); esto ocurre por vivir en un país en el que se premia la imbecilidad en lugar de la excelencia; hártense a Goyas hasta que les salgan por las orejas, otórgense premios los unos a los otros, cuélguense medallas, métanselas por donde les quepan. Ahora bien, no nos tomen por idiotas, joder.