lunes, 26 de mayo de 2014

Receta No. 3-3 en C#: Mejorar el Rendimiento de una Aplicación Evitando la Carga de Assemblies Innecesarios en Dominios de Aplicación

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Clase System.Runtime.Remoting.ObjectHandle
3.2 Ejemplo de uso
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

En la receta anterior aprendimos a cómo crear un tipo en un dominio de aplicación y permitir el intercambio de mensajes usando ese mismo objeto entre los dominios de aplicación; ahora llega la oportunidad de mejorar el rendimiento (desempeño) del proceso anterior evitando la carga de embalases innecesarios entre los distintos dominios de aplicación. Lo anterior nos obliga a estudiar la clase ObjectHandle (N:System.Runtime.Remoting) que es la que se encarga de (manera automática) llevar a cabo las tareas de carga y descarga de los assemblies en el dominio de aplicación remoto.

1. Problema

Nuestras dos soluciones software funcionan muy bien intercambiando mensajes entre ellas. Sin embargo, se ha notado una evidente degradación del desempeño de las dos aplicaciones debido a la carga de assemblies innecesarios (es decir, que son cargados en un momento oportuno, o muy tempranamente, lo que se traduce en un consumo ingente de recursos de máquina). Necesitamos una solución lo más pronto posible, de lo contrario los procesos de negocio de la compañía se verán gravemente afectos en un futuro cercano, como sabemos, debido a la latencia introducida por los artefactos introducidos anteriormente (cfr. Crear Tipos que Operen entre Diferentes Dominios de Aplicación).

2. Solución

Nuestro arquitecto de solución, inmediatamente se enteró de la desfavorable situación en cuanto al pobre rendimiento de las dos aplicaciones, nos ha sugerido ipso facto utilizar un artefacto que nos solucionará la carga temprana de assemblies innecesarios en los dominios de aplicación. El recurso que debemos utilizar concretamente es System.Runtime.Remoting.ObjectHandle.

3. Discusión de la Solución

Sabemos ahora que el recurso que nos va a ayudar a mejorar el rendimiento de nuestras aplicaciones, es ObjectHandle. A continuación detallada de uso: conceptos y ejemplos.

3.1 Clase System.Runtime.Remoting.ObjectHandle

La clase ObjectHandle [2] posee todos los elementos (miembros) que permiten envolver (término original: wraps) referencias de objeto por valor (MBV: marshal-by-value). Esto nos permite que al pasar un objeto entre distintos dominios de aplicación, se evita que la CLR (Common Language Runtime) cargue assemblies superfluos. Luego en el momento requerido, el objeto puede ser desenvuelto (término original: unwraps), de aquí en adelante ya es trabajo de la CLR cargar los assemblies necesarios, de tal manera que podamos crear referencias, y consecuentemente, utilizar los miembros de l objeto tal como lo haríamos con un objeto local.

3.1.1 Ejemplo de uso

En el siguiente ejemplo vamos a preparar un clase para ser utilizada en un dominio de aplicación remoto, pero adicionalmente vamos a hacer que se carguen los assemblies de esta clase en el instante que sea necesario. (Esta es la demostración de carga oportuna para ganar rendimiento y uso apropiado de los recursos del sistema).


En las líneas 24-35 se define la clase y su correspondiente cuerpo de miembros. Los miembros de esta clase:

  • NuevaClase(): Inicializa una instancia de NuevaClase y muestra en la salida estándar el código hash del dominio de aplicación en el que fue instanciada):

    AppDomain.CurrentDomain.GetHashCode()
  • ObtenerHashCodeDominioActual: Método que devuelve el código hash del dominio de aplicación actual de esta instancia.
En la línea 45 se muestra en pantalla el código hash del dominio de aplicación actual. Creamos un nuevo dominio (línea 48); desde este recién creado dominio, invocamos el método CreateDomain:

AppDomain nuevoAppDomain = AppDomain.CreateDomain("NuevoDominio");

Este dominio nos sirve en la línea 52 para crear una instancia de por medio del método CreateInstance [3] de AppDomain [4]:

ObjectHandle manejadorObjeto = nuevoAppDomain.CreateInstance(typeof(NuevaClase).Assembly.FullName.ToString(), "Recetas.Cap03.NuevaClase");

El objeto devuelto por CreateInstance es una instancia de ObjectHandle. Este es el que se encarga de envolver (wraps) le objeto para carga una carga posterior por parte de la CLR (precisamente, cuando se invoque el método Unwrap [5] sobre la instancia ObjectHandle; como en:

NuevaClase pruebaNuevaClase = (NuevaClase)manejadorObjeto.Unwrap();

> Prueba de ejecución.

Resultado:

Hashcode del dominio actual:
 -900862720

Creación de instancia de `NuevaClase` en el AppDomain: -75037952

El objeto recuperado con `manejadorObjeto.Unwrap` es un proxy (intermediario).

Invocación al método `pruebaNuevaClase.ObtenerHashCodeDominioActual` en el nuevo dominio: 
 -75037952

4. Práctica: Código Fuente C#

Ahora veamos (otro) ejemplo de uso de la clase ObjectHandle que se encarga de envolver (wraps) y desenvolver (unwraps) un objeto DataSet (System.Data):


Compilación:


  1. csc /target:exe WrapUnwrapDataSet.cs

Resultado:
Uso de ObjectHandle para (des)envolver una instancia de DataSet.
Figura 1. Uso de ObjectHandle para (des)envolver una instancia de DataSet.

5. Conclusiones

Hemos demostrado el uso de la clase ObjectHandle que es supremamente útil para mejorar el desempeño de aplicaciones que interacúan intercambiando mensajes entre sus diferentes dominios de aplicación. Los conceptos de envoltura (wrapping): cubrir una instancia con ObjectHandle para dejar que la CLR cargue (desenvuelva) la instancia en cuestión en el momento en que se requiera para uso.

6. Glosario

  • CLI
  • Desempeño
  • Desenvolver
  • Envolver
  • ObjectHandle
  • Rendimiento
  • Unwrap
  • Wraps

7. Literatura & Enlaces

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: ObjectHandle Class (System.Runtime.Remoting) - http://msdn.microsoft.com/en-us/library/system.runtime.remoting.objecthandle(v=vs.110).aspx
[3]: AppDomain.CreateInstance Method (String, String) (System) - http://msdn.microsoft.com/en-us/library/44s54yc4.aspx
[4]: AppDomain Class (System) - http://msdn.microsoft.com/en-us/library/System.AppDomain(v=vs.110).aspx
[5]: ObjectHandle.Unwrap Method (System.Runtime.Remoting) - http://msdn.microsoft.com/en-us/library/system.runtime.remoting.objecthandle.unwrap(v=vs.110).aspx
[6]: DataSet Class (System.Data) - http://msdn.microsoft.com/en-us/library/system.data.dataset(v=vs.110).aspx


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.